188

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.

Community
  • 1
  • 1
Jonathan Ong
  • 19,927
  • 17
  • 79
  • 118

9 Answers9

370

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


Basic example

.center-cropped {
  width: 100px;
  height: 100px;
  background-position: center center;
  background-repeat: no-repeat;
}
<div class="center-cropped" 
     style="background-image: url('https://via.placeholder.com/200');">
</div>

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.

.center-cropped {
  width: 100px;
  height: 100px;
  background-position: center center;
  background-repeat: no-repeat;
  overflow: hidden;
}

/* Set the image to fill its parent and make transparent */
.center-cropped img {
  min-height: 100%;
  min-width: 100%;
  /* IE 8 */
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
  /* IE 5-7 */
  filter: alpha(opacity=0);
  /* modern browsers */
  opacity: 0;
}
<div class="center-cropped" 
     style="background-image: url('https://via.placeholder.com/200');">
  <img src="https://via.placeholder.com/200" />
</div>

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:

.center-cropped {
  object-fit: none; /* Do not scale the image */
  object-position: center; /* Center the image within the element */
  height: 100px;
  width: 100px;
}
<img class="center-cropped" src="https://via.placeholder.com/200" />
Community
  • 1
  • 1
Russ Ferri
  • 6,459
  • 2
  • 22
  • 24
  • @TomSawyer Yes, using background-image is not ideal. If it is important to have an img tag for SEO, screenreaders, or otherwise, you can include one and hide it visually. http://jsfiddle.net/WN2kT/ – Russ Ferri Feb 24 '13 at 17:32
  • 54
    You can use `background-size: cover;` to get the image to shrink or fill the div appropriately while maintaining the original aspect ratio. – Nick Apr 30 '13 at 16:48
  • don't forget the background-repeat: no-repeat; if your image could be smaller (in height) that the height of your div – Guillaume Gendre Jul 31 '13 at 16:08
  • 7
    When using background-image you should add background-size:cover to properly size the cropped image: See http://jsfiddle.net/bw6ct/ – Kris Erickson Dec 18 '13 at 02:29
  • 2
    I've been told that nowdays Google knows about transparent and hidden images, so `img`'s `alt` ant `title` attributes will be lost for your SEO. – Victor Sergienko Apr 10 '14 at 16:43
  • I used this solution (and the background-size:cover) from @KrisErickson to solve an issue with cropping non-square profile images into circular profile images - see [blog post with example css](http://www.wombling.com/coding/scaling-or-cropping-profile-images-into-circles-when-the-source-isnt-a-square/) – wombling - Chris Paine Jul 15 '14 at 13:58
  • 7
    in webkit you can also use `object-fit: cover;` directly on the img tag which feels a bit more semantic. – Ben Nov 14 '14 at 02:20
  • @Ben Thanks for the heads up. I edited the answer to add an example w/ `object-fit`. I used a value of `none` here to prevent images larger than the desired square from scaling down. – Russ Ferri Nov 14 '14 at 04:53
  • 2
    I used object-fit: cover to get my desired effect of not losing aspect ratio, covering the square, and cropping if needed – Daniel Handojo Mar 25 '16 at 09:50
  • object-fit / position works perfectly for me - thank you! – Janos Aug 31 '18 at 12:17
90

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.

Jordi Vicens
  • 696
  • 7
  • 17
gluecksmelodie
  • 941
  • 6
  • 3
66

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

object-fit: cover;
Cleb
  • 25,102
  • 20
  • 116
  • 151
Roych
  • 673
  • 5
  • 10
24

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%);
}
Nathan Redblur
  • 632
  • 6
  • 12
  • Try this one... if image is smaller than the container it will center, otherwise it will crop http://jsfiddle.net/3ts4rm24/1/ – KnF Oct 29 '15 at 15:43
  • Why do you use `left: 50%` with `transform: translateX(-50%)`? – Oleg Yablokov Mar 23 '21 at 07:23
  • `left` is a position related to the container `translate` is related to the element if your container is 100px, and your picture is 20px, `left` will put the picture between the position 50px-70px. To fix that we rest the size of the picture with `translateX(-50%)` and then your picture will be between 40px-60px. Ej: if your container is 100px, `left: 50%` of this container rightMiddle = container/2 - element/2 – Nathan Redblur Mar 24 '21 at 13:16
9

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

mraaroncruz
  • 3,780
  • 2
  • 32
  • 31
  • 4
    Hiya downvoters. Please leave a comment so I can update my answer if there is a mistake. I don't like giving false info. Cheers. – mraaroncruz Oct 28 '16 at 15:19
  • Not a downvoter, but this is not an Angular question and your answer is irrelevant. @pferdefleisch – mawburn Jan 30 '17 at 14:52
  • 1
    @mburn that makes sense. It has been 3 years and this probably looks a little out of place or obnoxious now. I'll leave it up though because the upvotes on my comment tell me at least a couple people may find it useful (or they just don't like downvotes without comments). – mraaroncruz Jan 30 '17 at 18:46
2

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.

Alejandro Rizzo
  • 837
  • 2
  • 8
  • 14
  • in most case, this CSS is used repeatedly with different images. therefore, it is inevitable to set the background image inline. – Raptor Jan 15 '13 at 02:33
0

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.

Vedmant
  • 2,265
  • 1
  • 27
  • 36
0

for something like instagram explore or grid use this on img tag

aspect-ratio: 1 / 1; //or whatever
object-fit: cover;

note that parent has to have display of grid

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33906542) – Dhaval Purohit Feb 28 '23 at 18:01
0

Best of two worlds, some resize and then some croop, by double flexbox around image. Suitable to use for a full screen image (I use it for an image carousel) The width: 100vw and height: 100vh for container is the magic css.

HTML:

<div class="container">
   <div class="slide">
   <img src="https://someimageurl.jpg" 
   alt="image" class="image">
   </div>
</div>

CSS:

  .container {
  display: flex;
  position: relative;
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  justify-items: center;
  justify-content: center;
  }
 
 .slide {
 display: flex;
 width: 100%;
 height: 100%;
 max-width: 1600px;
 max-height: 1000px;
 justify-items: center;
 justify-content: center;
 margin: auto;
 padding: 0;
 overflow: hidden;
 }
 
 .image {
 display: block;
 min-width: 100%;
 min-height: 100%;
 object-fit: cover; /* Cover the image */
 object-position: center;
 margin: auto;
 padding: 0;
 }
Klas
  • 156
  • 1
  • 6