31
votes

So I have a collection of thumbnails in my app, which is the size of 200x200. Sometimes the original image doesn't have this ratio so I am planning to crop this image to a square.

Currently it just streches the image to fit into the thumbnail, so say my original image size is 400x800, then the image looks very squished. I wanted to crop this image so it looks at the shortest width/height and then crop it to a square, so in my example above it will be cropped to a 400x400.

Is there a way to easily do this via CSS or do I have to use some sort of JS to do this?

3
Although you did describe your problem, it is greatly appreciated to be able to see some code. Consider adding some code so that your question will have a much higher valueCody Guldner
@CodyGuldner, I think the point here is that his he doesn't know what code to use. His question seems fine to me.Jonah
@CodyGuldner if I had some code then I would really show it out here.. but I don't have any as of this pointadit
This is easily done if you can make the image be a background image of a div. Here is a fiddle showing how. If you need to use the img tag, then my css-fu is not good enough to help you, but I'll bet it's possible.Matt Greer
@Cody - if you crop an image, it wouldn't be the same aspect ratio.Samuel Liew♦

3 Answers

54
votes

You can do this easily in CSS if you use background-image.

.thumb {
    display: inline-block;
    width: 200px;
    height: 200px;
    margin: 5px;
    border: 3px solid #c99;
    background-position: center center;
    background-size: cover;
}

In this fiddle, first image is 400x800, second image is 800x400:

http://jsfiddle.net/samliew/tx7sf

9
votes

Updated to handle cases where image width is greater than height.

You can do this with pure CSS. Set the container element of each image to have fixed height and width and overflow: hidden. Then set the image within to have min-width: 100%, min-height: 100%. Any extra height or width will overflow the container and be hidden.

HTML

<div class="thumb">
    <img src="http://lorempixel.com/400/800" alt="" />
</div>

CSS

.thumb {
    display: block;
    overflow: hidden;
    height: 200px;
    width: 200px;
}

.thumb img {
    display: block; /* Otherwise it keeps some space around baseline */
    min-width: 100%;    /* Scale up to fill container width */
    min-height: 100%;   /* Scale up to fill container height */
    -ms-interpolation-mode: bicubic; /* Scaled images look a bit better in IE now */
}

Have a look at http://jsfiddle.net/thefrontender/XZP9U/5/

1
votes

I came up with my own solution and thought I would share it here in case anyone else found this thread. The background-size: cover solution is the easiest, but I needed something that would work in IE7 as well. Here's what I came up with using jQuery and CSS.

Note: My images were "profile" images and needed to be cropped to squares. Hence some of the function names.

jQuery:

cropProfileImage = function(pic){
    var h = $(pic).height(),
        w = $(pic).width();

    if($(pic).parent('.profile-image-wrap').length === 0){
                     // wrap the image in a "cropping" div
         $(pic).wrap('<div class="profile-image-wrap"></div>');
    }

      if(h > w ){
          // pic is portrait
          $(pic).addClass('portrait');
          var m = -(((h/w) * 100)-100)/2; //math the negative margin
          $(pic).css('margin-top', m + '%');    
      }else if(w > h){ 
          // pic is landscape
          $(pic).addClass('landscape'); 
          var m = -(((w/h) * 100)-100)/2;  //math the negative margin
          $(pic).css('margin-left', m + '%');
      }else {
        // pic is square
        $(pic).addClass('square');
      }
 }

// Call the function for the images you want to crop
cropProfileImage('img.profile-image');

CSS

.profile-image { visibility: hidden; } /* prevent a flash of giant image before the image is wrapped by jQuery */

.profile-image-wrap { 
      /* whatever the dimensions you want the "cropped" image to be */
      height: 8em;
      width: 8em;
      overflow: hidden; 
 }

.profile-image-wrap img.square {
      visibility: visible;
      width: 100%;  
 }

 .profile-image-wrap img.portrait {
      visibility: visible;
      width: 100%;
      height: auto;
 }

 .profile-image-wrap img.landscape {
      visibility: visible;
      height: 100%;
      width: auto;
 }