26

I have large images of varying dimensions that need to completely fill 240px by 300px containers in both dimensions. Here is what I got right now, which only works for one dimension:

http://jsfiddle.net/HsE6H/

HTML

<div class="container">
    <img src="http://placehold.it/300x1500">
</div>
<div class="container">
    <img src="http://placehold.it/1500x300">
</div

CSS

.container {
height: 300px;
width: 240px;
background-color: red;
float: left;
overflow: hidden;
margin: 20px;
}

img {
max-width: 100%;
height: auto;
}

The proportions should stay the same. Essentially, wide images should be cut off in width, while high images need to be cut off in height. So just zooming in as much as is needed to fill the container.

Not sure why I can't get it to work, do I need JavaScript for this?

Edit: To be clear. I need everything red on the fiddle gone. The images coming in are dynamic, therefore I can't use background-images. I'm open to using JavaScript. Thanks! :)

simanacci
  • 2,197
  • 3
  • 26
  • 35
Lennart
  • 327
  • 1
  • 5
  • 10
  • not sure about cross browser support - http://jsfiddle.net/HsE6H/2/ – Ruslan Polutsygan May 24 '13 at 16:51
  • Sorry, might not have been clear: I need the image to fill the whole div, so that all the "red" disappears. Any ideas? :) – Lennart May 24 '13 at 16:53
  • 1
    You will not be able to take "large images of varying dimensions" and perfectly fit them to a container of fixed dimensions without scaling the two axes at separate ratios. If you scale an image proportionately, then the proportions of the source will be the same as the target. – Blaise Swanwick May 24 '13 at 17:02
  • Like `Blaise Swanwick` said it's not possible only by `css` you need to resize images using some server side code and image manipulation library. – The Alpha May 24 '13 at 17:12
  • Any ideas how to go about that? Very open to solutions involving JS. – Lennart May 24 '13 at 17:14
  • Sounds like you're looking for the object-fit property, but only 1 browser supports it: http://dev.opera.com/articles/view/css3-object-fit-object-position/ – cimmanon May 24 '13 at 17:15
  • Possible duplicate of http://stackoverflow.com/questions/1891857/how-do-you-stretch-an-image-to-fill-a-div-while-keeping-the-images-aspect-rat – User Nov 29 '15 at 19:35
  • this did not do the job for you ? http://jsfiddle.net/HsE6H/181/ cuts off image too wide or too tall – G-Cyrillus Mar 05 '16 at 22:49

13 Answers13

43

Auto-sizing Images to Fit a Div - Making the CSS Work

Here is one way of doing it, start with the following HTML:

<div class="container portrait">
    <h4>Portrait Style</h4>
    <img src="http://placekitten.com/150/300">
</div>

and the CSS:

.container {
    height: 300px;
    width: 240px;
    background-color: red;
    float: left;
    overflow: hidden;
    margin: 20px;
}
.container img {
    display: block;
}

.portrait img {
    width: 100%;
}
.landscape img {
    height: 100%;
}

and the demo fiddle: http://jsfiddle.net/audetwebdesign/QEpJH/

When you have an image oriented as a portrait, you need to scale the width to 100%. Conversely, when the image is landscape oriented, you need to scale the height.

Unfortunately, there is no combination of selectors in CSS that targets the aspect ratio of the image, so you can't use CSS to pick out the correct scaling.

In addition, you have no easy way of centering the image since the top left corner of the image is pinned to the top left corner of the containing block.

jQuery Helper

You can use the following jQuery action to determine which class to set based on the aspect ratio of the image.

$(".container").each(function(){
    // Uncomment the following if you need to make this dynamic
    //var refH = $(this).height();
    //var refW = $(this).width();
    //var refRatio = refW/refH;

    // Hard coded value...
    var refRatio = 240/300;

    var imgH = $(this).children("img").height();
    var imgW = $(this).children("img").width();

    if ( (imgW/imgH) < refRatio ) { 
        $(this).addClass("portrait");
    } else {
        $(this).addClass("landscape");
    }
})

For each image in .container, get the height and width, test if width<height and then set the appropriate class.

Also, I added a check to take into account the aspect ratio of the containing block. Before, I had implicitly assumed a square view panel.

Marc Audet
  • 46,011
  • 11
  • 63
  • 83
5

For anyone looking to do this that doesn't have dynamic images, here's an all-CSS solution using background-image.

<div class="container" 
    style="background-image: url('http://placehold.it/300x1500'); 
    background-size: cover; background-position: center;">
</div>
<div class="container" 
    style="background-image: url('http://placehold.it/1500x300'); 
    background-size: cover; background-position: center;">
</div>

The "background-size: cover" makes it so that the image scales to cover all of the div while maintaining the aspect ratio. The CSS could also be moved to a CSS file. Although if it's dynamically generated, the background-image property will have to stay in the style attribute.

BurningLights
  • 2,387
  • 1
  • 15
  • 22
3

Taking out the line: max-width:100% in your CSS file seems to do the trick.

.container {
height: 300px;
width: 240px;
background-color: red;
float: left;
overflow: hidden;
margin: 20px;
}

img {
height: auto;
}

Also you can add > to your closing div in your HTML file could make the code neater.

<div class="container">
    <img src="http://placehold.it/300x1500">
</div>
<div class="container">
    <img src="http://placehold.it/1500x300">
</div>

Here is a working JSFiddle link: http://jsfiddle.net/HsE6H/19/

Jcpopp
  • 149
  • 9
  • Yeah, the placeholder images are a bit misleading there. This just makes the images full size, while I would like them to be as small as possible while still filling the whole container. – Lennart May 24 '13 at 17:10
3

Here is another solution I found, that no need to seperate portraid or landscape or scripting.

  <div class="container">
    <img src="http://placehold.it/500x500" class="pic" />
  </div>

CSS

.container{
  position: relative;
  width: 500px;
  height: 300px;
  margin-top: 30px;
  background: #4477bb;
}
.pic{
    max-width: 100%;
    width: auto;
    max-height: 100%;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
}

Here it is, it works well...

https://jsfiddle.net/efirat/17bopn2q/2/

efirat
  • 3,679
  • 2
  • 39
  • 43
  • 1
    Just the solution I was looking for. Shame it does not answer the question above. I think they wanted to fill the container completely, even if part of the image gets cropped. So the blue areas should not be visible. – jumxozizi Jul 30 '17 at 11:25
  • @Rubiksmomo sorry, I have just canalize my own problem, you are right. Question is different, but, this code also work for others... Thank you. – efirat Aug 01 '17 at 06:49
2

Background can do this

  1. set image as background

2.

div {
   -webkit-background-size: auto 100%;
   -moz-background-size: auto 100%;
   -o-background-size: auto 100%;
   background-size: auto 100%;
}

or

div {
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}
Tim Kozak
  • 4,026
  • 39
  • 44
  • 1
    Thank you sir! I can't believe nobody upped this.. here is a test: https://jsfiddle.net/yrrncees/8/ – Alex Mar 04 '16 at 17:07
  • Worth noting that when using this solution, it's a good idea to include a hidden version of the image within the div for accessibilities sake. That way you can set the alt tag, and users with CSS disabled can still view the site and see the images. If doing this it's better to avoid `display: none` as some screen readers will skip over elements with those styles. – kravse Mar 07 '16 at 16:35
  • Just a note as of 2017/Sep background-image do not print, in chrome you can set a style to get them to print but in other browsers not so. – Robin Luiten Sep 05 '17 at 02:17
2

You should try this:

img {
    min-width:100%;
    min-height:100%;
}
2

I used this plugin that accounts for any ratio. It also requires imagesloaded plugin to work. This would be useful for numerous images across a site needing this treatment. Simple to initiate too.

https://github.com/johnpolacek/imagefill.js/

sledgeweight
  • 7,685
  • 5
  • 31
  • 45
2

It works if you add the following to the parent div for img styling; https://jsfiddle.net/yrrncees/10/

.container img {
position: relative;
vertical-align: middle;
top: 50%;
-webkit-transform: translateY(-50%);
min-height: 100%;
min-width: 100%;
object-fit:cover;
}
0

This could do the job:

.container {
    float: left;
    height: 300px;
    width: 240px;
    background-color: red;
    margin: 20px;
}

img {
    width:240px;
    height:300px;
}
SAST
  • 11
  • 1
0

We went down the path with an Angular app of using a variation on the jQuery approach above. Then one of our bright colleagues came up with a pure CSS approach. See this example here: https://jsfiddle.net/jeffturner/yrrncees/1/.

Basically using line-height solved the problem for us. For those not wanting to hit the fiddle, the code fragments are:

.container {
    margin: 10px;
    width: 125px;
    height: 125px;
    line-height: 115px;
    text-align: center;
    border: 1px solid red;
}
.resize_fit_center {
    max-width:100%;
    max-height:100%;
    vertical-align: middle;
}

The key is in using line-height and setting the container to do the same.

  • OP (and me in fact) is looking for a solution where the image fills the div without leaving background whitespace. Unfortunately this doesn't do that. – Daryl Teo Jun 16 '15 at 12:44
0

I came across this topic because I was trying to solve a similar problem. Then a lightbulb went off in my head and I couldn't believe it worked because it was so simple and so obvious.

CSS

.container {
height: 300px;
width: 240px;
background-color: red;
float: left;
overflow: hidden;
margin: 20px;
}

img {
min-width:100%;
min-height:100%;
}

Just set the min-width and min-height to 100% and it will always automatically resize to fit the div, cutting off the excess image. No muss no fuss.

0

Using an image as Div background has many disadvantages (like missing ALT for SEO). Instead of it, use object-fit: cover; in the image tag style!

cokeman19
  • 2,405
  • 1
  • 25
  • 40
Mehdi Saghari
  • 154
  • 1
  • 9
0

The following solution is very short and clean if you need to insert img tag into div tag:

.container, .container img 
{
 max-height: 300px;
 max-width: 240px;
}
Try to open every image into another page you will notice that originals are all different sized but none is streched, just zoomed:
<p></p>

<div class="container"><img src="https://www.gentoo.org/assets/img/screenshots/surface.png" /></div>
<p></p>
<div class="container"><img src="https://cdn.pixabay.com/photo/2011/03/22/22/25/winter-5701_960_720.jpg" /></div>
<p></p>
<div class="container"><img src="https://cdn.arstechnica.net/wp-content/uploads/2009/11/Screenshot-gnome-shell-overview.png" /></div>
<p></p>
<div class="container"><img src="http://i.imgur.com/OwFSTIw.png" /></div>
<p></p>
<div class="container"><img src="https://www.gentoo.org/assets/img/screenshots/surface.png" /></div>
<p></p>
<div class="container"><img src="https://freebsd.kde.org/img/screenshots/uk_maximignatenko_kde420-1.png" /></div>
<p></p>
<div class="container"><img src="https://i.ytimg.com/vi/9mrOgkYje0s/maxresdefault.jpg" /></div>
<p></p>
<div class="container"><img src="https://upload.wikimedia.org/wikipedia/commons/5/59/Linux_screenshot.jpg" /></div>
<p></p>

Also, if you don't need to use a div you can just write an even shorter css:

 img
    {
        max-height: 300px;
        max-width: 240px;
    }
willy wonka
  • 1,440
  • 1
  • 18
  • 31