67

I want to contain an image into a 250 x 250 div, forcing the image to resize but not stretch. How can I do this? By the way, the image will usually be bigger than the div itself, which is why resizing comes into the picture.

<div id = "container">
  <img src = "whatever" />
</div>

#container { width:250px; height:250px; border:1px solid #000; }

Here's a jsfiddle which someone can edit:

http://jsfiddle.net/rV77g/

varatis
  • 14,494
  • 23
  • 71
  • 114

7 Answers7

89

object-fit, behaves like background-size, solving the issue of scaling images up and down to fit.

The object-fit CSS property specifies how the contents of a replaced element should be fitted to the box established by its used height and width.

https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

snapshot of an image rendered with all the object-fit options

.cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    overflow: hidden;
}

Browser Support

There's no IE support, and support in Edge begins at v16, only for img element: https://caniuse.com/#search=object-fit

The bfred-it/object-fit-images polyfill works very well for me in IE11, tested on Browserstack: demo.


Alternative without polyfill using an image in SVG

For Edge pre v16, and ie9, ie10, ie11:

You can crop and scale any image using CSS object-fit and object-position. However, these properties are only supported in the latest version of MS Edge as well as all other modern browsers.

If you need to crop and scale an image in Internet Explorer and provide support back to IE9, you can do that by wrapping the image in an <svg>, and using the viewBox and preserveAspectRatio attributes to do what object-fit and object-position do.

http://www.sarasoueidan.com/blog/svg-object-fit/#summary-recap

(The author explains the technique thoroughly, and duplicating the detail here would be impractical.)

ptim
  • 14,902
  • 10
  • 83
  • 103
  • hmm.. maybe a jsfiddle is easier to view: https://jsfiddle.net/memeLab/17tn9c18/1/embedded/result/ – ptim Feb 15 '15 at 14:13
  • Would be great if it was supported by IE, unfortunately it's not really usable in commercial work as even the latest IE doesn't handle it. – DBS Jul 08 '15 at 14:24
  • Even with the (lack of) IE support weighted in, the accepted answer should be changed to this as it also scales small images up, not just big ones down. Any company that takes itself seriously should just disable it's site entirely on IE or at least show a message that some features may not work properly and the user should change browsers to be able to use the site properly. – sisisisi Jul 28 '20 at 23:38
  • this worked for me after I set height: 100px on the wrapping container ... I don't think it knew what height: 100% was ... great example thx – danday74 Aug 25 '23 at 13:33
53

Use max width and max height. It will keep the aspect ratio

#container img 
{
 max-width: 250px;
 max-height: 250px;
}

http://jsfiddle.net/rV77g/

egrunin
  • 24,650
  • 8
  • 50
  • 93
Oliver
  • 1,490
  • 18
  • 19
  • 2
    +1 for keeping the aspect. Won't scale it when the image is smaller, though. – JimmiTh Jan 30 '12 at 22:40
  • 2
    @TheKaneda: this is a good point. If this is desired, the code should be modified to include min-width and min-height – Ben D Jan 30 '12 at 22:42
  • 1
    @Ben D: That would only work with both dimensions on the same side of the 250 pixels. If width of image is 240px and height is 260px, width will be scaled to 250px (to comply with min-width) while height will be scaled to 250px (to comply with max-height). – JimmiTh Jan 30 '12 at 22:49
  • 1
    @TheKaneda: You're right, of course. At least I got two upvotes for while making an obvious mistake :) – Ben D Jan 30 '12 at 22:54
  • This alternative doesn't works if the image is smaller than both max-width and max-height. – Guillermo Gutiérrez Feb 17 '14 at 19:33
  • This works! But using values is always a headache. – Chinmay Ghule Sep 12 '21 at 06:40
16

You have to style the image like this

#container img{width:100%;}

and the container with hidden overflow:

#container{width:250px; height:250px; overflow:hidden; border:1px solid #000;} 
1

Here is javascript I wrote to do just this.

function ImageTile(parentdiv, imagediv) {
imagediv.style.position = 'absolute';

function load(image) {
    //
    // Reset to auto so that when the load happens it resizes to fit our image and that
    // way we can tell what size our image is. If we don't do that then it uses the last used
    // values to auto-size our image and we don't know what the actual size of the image is.
    //
    imagediv.style.height = "auto";
    imagediv.style.width = "auto";
    imagediv.style.top = 0;
    imagediv.style.left = 0;

    imagediv.src = image;
}

//bind load event (need to wait for it to finish loading the image)
imagediv.onload = function() {
    var vpWidth = parentdiv.clientWidth;
    var vpHeight = parentdiv.clientHeight;
    var imgWidth = this.clientWidth;
    var imgHeight = this.clientHeight;

    if (imgHeight > imgWidth) {
        this.style.height = vpHeight + 'px';
        var width = ((imgWidth/imgHeight) * vpHeight);
        this.style.width = width + 'px';
        this.style.left = ((vpWidth - width)/2) + 'px';
    } else {
        this.style.width = vpWidth + 'px';
        var height = ((imgHeight/imgWidth) * vpWidth);
        this.style.height = height + 'px';
        this.style.top = ((vpHeight - height)/2) + 'px';
    }
};

return {
    "load": load
};

}

And to use it just do something like this:

 var tile1 = ImageTile(document.documentElement, document.getElementById("tile1"));
 tile1.load(url);

I use this for a slideshow in which I have two of these "tiles" and I fade one out and the other in. The loading is done on the "tile" that is not visible to avoid the jarring visual affect of the resetting of the style back to "auto".

crowmagnumb
  • 6,621
  • 9
  • 33
  • 42
1

Since you don't want stretching (all of the other answers ignore that) you can simply set max-width and max-height like in my jsFiddle edit.

#container img {
    max-height: 250px;
    max-width: 250px;
} 

See my example with an image that isn't a square, it doesn't stretch

MMM
  • 7,221
  • 2
  • 24
  • 42
-2
  <div id ="container">
    <img src = "http://animalia-life.com/data_images/duck/duck9.jpg"/>
#container img {
        max-width:250px;
        max-height:250px;
        width: 250px;
        height: 250px;
        border:1px solid #000;
    }

The img will lose aspect ratio

daniel
  • 1
  • 1
    The question specifically mentions they want to force the image to resize but not stretch, meaning the they want to maintain aspect ratio. – Andrew Winter Jul 11 '16 at 22:53
-2
#container img{
 height:100%;
 width:100%;   
}
IsisCode
  • 2,490
  • 18
  • 20