[css] How to automatically crop and center an image

Given any arbitrary image, I want to crop a square from the center of the image and display it within a given square.

This question is similar to this: CSS Display an Image Resized and Cropped, but I don't know the size of the image so I can't use set margins.

This question is related to css

The answer is


One solution is to use a background image centered within an element sized to the cropped dimensions.


Basic example

_x000D_
_x000D_
.center-cropped {_x000D_
  width: 100px;_x000D_
  height: 100px;_x000D_
  background-position: center center;_x000D_
  background-repeat: no-repeat;_x000D_
}
_x000D_
<div class="center-cropped" _x000D_
     style="background-image: url('http://placehold.it/200x200');">_x000D_
</div>
_x000D_
_x000D_
_x000D_


Example with img tag

This version retains the img tag so that we do not lose the ability to drag or right-click to save the image. Credit to Parker Bennett for the opacity trick.

_x000D_
_x000D_
.center-cropped {_x000D_
  width: 100px;_x000D_
  height: 100px;_x000D_
  background-position: center center;_x000D_
  background-repeat: no-repeat;_x000D_
  overflow: hidden;_x000D_
}_x000D_
_x000D_
/* Set the image to fill its parent and make transparent */_x000D_
.center-cropped img {_x000D_
  min-height: 100%;_x000D_
  min-width: 100%;_x000D_
  /* IE 8 */_x000D_
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";_x000D_
  /* IE 5-7 */_x000D_
  filter: alpha(opacity=0);_x000D_
  /* modern browsers */_x000D_
  opacity: 0;_x000D_
}
_x000D_
<div class="center-cropped" _x000D_
     style="background-image: url('http://placehold.it/200x200');">_x000D_
  <img src="http://placehold.it/200x200" />_x000D_
</div>
_x000D_
_x000D_
_x000D_


object-fit/-position

See supported browsers.

The CSS3 Images specification defines the object-fit and object-position properties which together allow for greater control over the scale and position of the image content of an img element. With these, it will be possible to achieve the desired effect:

_x000D_
_x000D_
.center-cropped {_x000D_
  object-fit: none; /* Do not scale the image */_x000D_
  object-position: center; /* Center the image within the element */_x000D_
  height: 100px;_x000D_
  width: 100px;_x000D_
}
_x000D_
<img class="center-cropped" src="http://placehold.it/200x200" />
_x000D_
_x000D_
_x000D_


Example with img tag but without background-image

This solution retains the img tag so that we do not lose the ability to drag or right-click to save the image but without background-image just center and crop with css.

Maintain the aspect ratio fine except in very hight images. (check the link)

(view in action)

Markup

<div class="center-cropped">
    <img src="http://placehold.it/200x150" alt="" />
</div>

? CSS

div.center-cropped {
  width: 100px;
  height: 100px;
  overflow:hidden;
}
div.center-cropped img {
  height: 100%;
  min-width: 100%;
  left: 50%;
  position: relative;
  transform: translateX(-50%);
}

There is another way you can crop image centered:

.thumbnail{position: relative; overflow: hidden; width: 320px; height: 640px;}
.thumbnail img{
    position: absolute; top: -999px; bottom: -999px; left: -999px; right: -999px;
    width: auto !important; height: 100% !important; margin: auto;
}
.thumbnail img.vertical{width: 100% !important; height: auto !important;}

The only thing you will need is to add class "vertical" to vertical images, you can do it with this code:

jQuery(function($) {
    $('img').one('load', function () {
        var $img = $(this);
        var tempImage1 = new Image();
        tempImage1.src = $img.attr('src');
        tempImage1.onload = function() {
            var ratio = tempImage1.width / tempImage1.height;
            if(!isNaN(ratio) && ratio < 1) $img.addClass('vertical');
        }
    }).each(function () {
        if (this.complete) $(this).load();
    });
});

Note: "!important" is used to override possible width, height attributes on img tag.


I created an angularjs directive using @Russ's and @Alex's answers

Could be interesting in 2014 and beyond :P

html

<div ng-app="croppy">
  <cropped-image src="http://placehold.it/200x200" width="100" height="100"></cropped-image>
</div>

js

angular.module('croppy', [])
  .directive('croppedImage', function () {
      return {
          restrict: "E",
          replace: true,
          template: "<div class='center-cropped'></div>",
          link: function(scope, element, attrs) {
              var width = attrs.width;
              var height = attrs.height;
              element.css('width', width + "px");
              element.css('height', height + "px");
              element.css('backgroundPosition', 'center center');
              element.css('backgroundRepeat', 'no-repeat');
              element.css('backgroundImage', "url('" + attrs.src + "')");
          }
      }
  });

fiddle link


Try this: Set your image crop dimensions and use this line in your CSS:

object-fit: cover;

Try this:

#yourElementId
{
    background: url(yourImageLocation.jpg) no-repeat center center;
    width: 100px;
    height: 100px;
}

Keep in mind that width and height will only work if your DOM element has layout (a block displayed element, like a div or an img). If it is not (a span, for example), add display: block; to the CSS rules. If you do not have access to the CSS files, drop the styles inline in the element.


I was looking for a pure CSS solution using img tags (not the background image way).

I found this brilliant way to achieve the goal on crop thumbnails with css:

.thumbnail {
  position: relative;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.thumbnail img {
  position: absolute;
  left: 50%;
  top: 50%;
  height: 100%;
  width: auto;
  -webkit-transform: translate(-50%,-50%);
      -ms-transform: translate(-50%,-50%);
          transform: translate(-50%,-50%);
}
.thumbnail img.portrait {
  width: 100%;
  height: auto;
}

It is similar to @Nathan Redblur's answer but it allows for portrait images, too.

Works like a charm for me. The only thing you need to know about the image is whether it is portrait or landscape in order to set the .portrait class so I had to use a bit of Javascript for this part.