How do you stretch an image to fill a <div> while keeping the image's aspect-ratio?
Asked Answered
S

19

251

I need to make this image stretch to the maximum size possible without overflowing it's <div> or skewing the image.

I can't predict the aspect-ratio of the image, so there's no way to know whether to use:

<img src="url" style="width: 100%;">

or

<img src="url" style="height: 100%;">

I can't use both (i.e. style="width: 100%; height: 100%;") because that will stretch the image to fit the <div>.

The <div> has a size set by percentage of the screen, which is also unpredictable.

Splitlevel answered 12/12, 2009 at 1:16 Comment(4)
If you need the image to fill either height or width to the corresponding dimensions of the div, I can only think of using javascript. Is that something you are keen to explore?Ingeingeberg
Related: #788339Crosstie
The answer is object-fit, see (and upvote) @daniels belowKassiekassity
@aexl Thanks for alerting me to this. This question is 11.5 years old and I accepted that answer the same day. XD I selected a different answer, that seems to be more relevant than the one you mentioned. Let me know if you disagree. I'm actually not a web developer, just C++, so I wouldn't know much about choosing the best answer here.Splitlevel
C
71

If you're able to set the image as a background-image then you can do something like this, which will crop the image without stretching it:

<div style="background-image: url(...); background-size: cover; width: 100%; height: 100%;"></div>

If you need to stick with an <img> tag, then as of 2019, you can now use the object-fit css property that accepts the following values:
fill | contain | cover | none | scale-down

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

As an example, you could have a container that holds an image:

<div class="container">
    <img src="" class="container_img" />
</div>

.container {
    height: 50px;
    width: 50%;
}

.container_img {
    height: 100%;
    width: 100%;
    object-fit: cover;
} 
Custard answered 25/6, 2019 at 8:49 Comment(0)
C
207

Update 2016:

Modern browser behave much better. All you should need to do is to set the image width to 100% (demo)

.container img {
   width: 100%;
}

Since you don't know the aspect ratio, you'll have to use some scripting. Here is how I would do it with jQuery (demo):

CSS

.container {
    width: 40%;
    height: 40%;
    background: #444;
    margin: 0 auto;
}
.container img.wide {
    max-width: 100%;
    max-height: 100%;
    height: auto;
}
.container img.tall {
    max-height: 100%;
    max-width: 100%;
    width: auto;
}​

HTML

<div class="container">
 <img src="http://i48.tinypic.com/wrltuc.jpg" />
</div>
<br />
<br />
<div class="container">
 <img src="http://i47.tinypic.com/i1bek8.jpg" />
</div>

Script

$(window).load(function(){
 $('.container').find('img').each(function(){
  var imgClass = (this.width/this.height > 1) ? 'wide' : 'tall';
  $(this).addClass(imgClass);
 })
})
Crosstie answered 12/12, 2009 at 8:57 Comment(14)
Can the user see the image before the resize? Anyone tested this?Voorhees
The solution is almost right, you just have to invert the height and width in the css : if the image is 'tall', then the width should be 100% not the height (wich will be bigger and overflowing). The other way around for the wide photos.Hepato
@mbritto: You're right, I had to change the css to max-width/height and I added a demoCrosstie
@Crosstie is there a way to fit a image of size 930 px width to a container of 960 px without losing the image qualityKuth
@VivekDragon Image quality will always suffer when stretching. The best thing to do is to just have the image at the size you want it.Crosstie
Why is this the accepted answer. The question is about images being too small for their container. i.e. how can an image be scaled up to fill its container's width or height, without fudging up the image's aspect ratio. Also, in your demo, removing the width:auto or height:auto properties does not affect the display of your images. As a matter of fact, of all the properties you're applying to the image, only max-width: 100% has any effect at all, and it only effects the landscape image. But most importantly, your answer does not help stretch a small image to fill a larger container.Knighthood
Useless code, demo shows nothing at all. w3schools.com/cssref/pr_dim_height.asp Default value for Height and Width is 'auto'. How your 'height: auto;' and 'width: auto;' should influence the element? Other styles for 2 classes are the same. Any idea why this answer got 77 upvotes?Lyonnais
@Lyonnais Yes, the default value is auto, you're forcing the image to adjust its size automatically, but limit it in one direction. Also consider that it was answered in 2009... Did you try resizing the result pane in the demo?Crosstie
@Crosstie but limit it in one direction - how? Both height and weight is set to auto by default. You set manually height to auto. What changed? 'was answered in 2009' - understand but answer is still on high positions in the search results so making it up-to-date would be awesome from your side =)Lyonnais
@Lyonnais I've updated my answer. Interestingly enough, it seems you only need to set the width.Crosstie
How about you try background-size: auto 100%; (source:w3schools.com/cssref/css3_pr_background-size.asp)Hautesavoie
Shouldn't you also have a $(this).removeClass(<the other class in case it's already there?>)?Betthezel
No @Chiwda, the class names are only added on window load.Crosstie
why this needs jQuery for a simple img in a div? Maybe there is more of a simple wayHoffarth
H
103

There is a much easier way to do this using only CSS and HTML:

HTML:

<div 
    class="fill" 
    style="background-image: url('path/to/image.jpg');">
</div>

CSS:

.fill {
    background-size: cover;
    background-position: center;
    width: 100%;
    height: 100%;
}

This will place your image as the background, and stretch it to fit the div size without distortion.

Hifalutin answered 6/5, 2014 at 1:6 Comment(6)
is this possible with an undefined number of images ?Unvoice
background-size: cover; is the real magic here, and it's CSS3 but has reasonable browser support on most recent versions (see: w3schools.com/cssref/css3_pr_background-size.asp )Boorish
It might be worth including the image url in the HTML, in order to separate style and contents, i.e. <div style="background-image: url('path/to/image.jpg');" class="fill"></div>Vasiliu
background-size: cover does not maintain the aspect ratio, parts of the image that are not proportional to the element are cropped. Refer herePlasticity
@Alex_Zhong, you misunderstand aspect ratio. Aspect ratio means that the image is not stretched in any direction (so a perfect circle would not become an oval in either width or height). Cropping may be a necessary part of maintaining aspect ratio (as it is in the OP's use case).Biramous
It works for Django too.Dunlavy
M
74

Not a perfect solution, but this CSS might help. The zoom is what makes this code work, and the factor should theoretically be infinite to work ideally for small images - but 2, 4, or 8 works fine in most cases.

#myImage {
    zoom: 2;  //increase if you have very small images

    display: block;
    margin: auto;

    height: auto;
    max-height: 100%;

    width: auto;
    max-width: 100%;
}
Miller answered 22/2, 2012 at 2:12 Comment(3)
I wish this worked in Firefox. Why no zoom love from Firefox!?Knighthood
Firefox still doesn't have zoom implemented, but here is the bug link for future reference: bugzilla.mozilla.org/show_bug.cgi?id=390936Unhandled
I love this, I save it as .stretchy and make great use of it.Vlaminck
C
71

If you're able to set the image as a background-image then you can do something like this, which will crop the image without stretching it:

<div style="background-image: url(...); background-size: cover; width: 100%; height: 100%;"></div>

If you need to stick with an <img> tag, then as of 2019, you can now use the object-fit css property that accepts the following values:
fill | contain | cover | none | scale-down

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

As an example, you could have a container that holds an image:

<div class="container">
    <img src="" class="container_img" />
</div>

.container {
    height: 50px;
    width: 50%;
}

.container_img {
    height: 100%;
    width: 100%;
    object-fit: cover;
} 
Custard answered 25/6, 2019 at 8:49 Comment(0)
P
38

If you can, use background images and set background-size: cover. This will make the background cover the whole element.

CSS

div {
  background-image: url(path/to/your/image.png);
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: cover;
}

If you're stuck with using inline images there are a few options. First, there is

object-fit

This property acts on images, videos and other objects similar to background-size: cover.

CSS

img {
  object-fit: cover;
}

Sadly, browser support is not that great with IE up to version 11 not supporting it at all. The next option uses jQuery

CSS + jQuery

HTML

<div>
  <img src="image.png" class="cover-image">
</div>

CSS

div {
  height: 8em;
  width: 15em;
}

Custom jQuery plugin

(function ($) {
  $.fn.coverImage = function(contain) {
    this.each(function() {
      var $this = $(this),
        src = $this.get(0).src,
        $wrapper = $this.parent();

      if (contain) {
        $wrapper.css({
          'background': 'url(' + src + ') 50% 50%/contain no-repeat'
        });
      } else {
        $wrapper.css({
          'background': 'url(' + src + ') 50% 50%/cover no-repeat'
        });
      }

      $this.remove();
    });

    return this;
  };
})(jQuery);

Use the plugin like this

jQuery('.cover-image').coverImage();

It will take an image, set it as a background image on the image's wrapper element and remove the img tag from the document. Lastly you could use

Pure CSS

You might use this as a fallback. The image will scale up to cover it's container but it won't scale down.

CSS

div {
  height: 8em;
  width: 15em;
  overflow: hidden;
}

div img {
  min-height: 100%;
  min-width: 100%;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  display: block;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Hope this might help somebody, happy coding!

Pisano answered 14/5, 2015 at 16:54 Comment(4)
I was looking for a pure CSS solution to have images fill a given container without using background-image & background-size and the CSS code here works great for >=IE9 and modern browsers. CodePen demo hereSheritasherj
In Pure CSS, I removed min- and change to width: 100%; height: 100%; and work! awesome solution! +1 Thanks!Fenny
background-size: contain is also useful if you want none of the image to ever be clipped.Adhamh
You can add zoom:0.001 to the Pure CSS solution to scale down.Synchromesh
A
20

Thanks to CSS3

img
{
   object-fit: contain;
}

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

IE and EDGE as always outsiders: http://caniuse.com/#feat=object-fit

Annabelleannabergite answered 18/4, 2016 at 12:15 Comment(0)
S
7

That's impossible with just HTML and CSS, or at least wildly exotic and complicated. If you're willing to throw some javascript in, here's a solution using jQuery:

$(function() {
    $(window).resize(function() {
        var $i = $('img#image_to_resize');
        var $c = $img.parent();
        var i_ar = $i.width() / $i.height(), c_ar = $c.width() / $c.height();            
        $i.width(i_ar > c_ar ? $c.width() : $c.height() * (i_ar));
    });
    $(window).resize();
});

That will resize the image so that it will always fit inside the parent element, regardless of it's size. And as it's binded to the $(window).resize() event, when user resizes the window, the image will adjust.

This does not try to center the image in the container, that would be possible but I guess that's not what you're after.

Superfuse answered 12/12, 2009 at 1:55 Comment(2)
I assume $img.parent(); should really be $i.parent();Onus
today is possible. { width: auto; max-width: none; max-height: 100%; object-fit: contain; }Summersummerhouse
S
6

You can use object-fit: cover; on the parent div.

https://css-tricks.com/almanac/properties/o/object-fit/

Synsepalous answered 13/8, 2015 at 10:21 Comment(2)
No IE or Edge support on this yet unfortunately :( caniuse.com/#feat=object-fitLafrance
width: auto; max-width: none; max-height: 100%; object-fit: contain;Summersummerhouse
C
5

Set width and height of the outer container div. Then use below styling on img:

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

This will help you to keep an aspect ratio of your img

Confessedly answered 14/3, 2014 at 13:19 Comment(1)
it wont fill the div.Cuneate
D
5

If you want to set a max width or height (so that it will not be very large) while keeping the images aspect-ratio, you can do this:

img{
   object-fit: contain;
   max-height: 70px;
}
Decimal answered 2/6, 2018 at 11:0 Comment(0)
S
4

I came across this question searching for a simular problem. I'm making a webpage with responsive design and the width of elements placed on the page is set to a percent of the screen width. The height is set with a vw value.

Since I'm adding posts with PHP and a database backend, pure CSS was out of the question. I did however find the jQuery/javascript solution a bit troblesome, so I came up with a neat (so I think myself at least) solution.

HTML (or php)

div.imgfill {
  float: left;
  position: relative;
  background-repeat: no-repeat;
  background-position: 50%  50%;
  background-size: cover;
  width: 33.333%;
  height: 18vw;
  border: 1px solid black; /*frame of the image*/
  margin: -1px;
}
<div class="imgfill" style="background-image:url(source/image.jpg);">
  This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image2.jpg);">
  This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image3.jpg);">
  This might be some info
</div>

By using style="" it's posible to have PHP update my page dynamically and the CSS-styling together with style="" will end up in a perfectly covered image, scaled to cover the dynamic div-tag.

Stovepipe answered 26/4, 2016 at 11:17 Comment(0)
O
4

To make this image stretch to the maximum size possible without overflowing it's or skewing the image.

Apply...

img {
  object-fit: cover;
  height: -webkit-fill-available;
}

styles to the image.

Orang answered 12/12, 2017 at 17:52 Comment(0)
P
3

Using this method you can fill in your div with the image varying ratio of divs and images.

jQuery:

$(window).load(function(){
   $('body').find(.fillme).each(function(){
      var fillmeval = $(this).width()/$(this).height();
      var imgval = $this.children('img').width()/$this.children('img').height();
      var imgClass;
      if(imgval > fillmeval){
          imgClass = "stretchy";
      }else{
          imgClass = "stretchx";
      }
      $(this).children('img').addClass(imgClass);
   });
});

HTML:

<div class="fillme">
   <img src="../images/myimg.jpg" />
</div>

CSS:

.fillme{
  overflow:hidden;
}
.fillme img.stretchx{
  height:auto;
  width:100%;
}
.fillme img.stretchy{
  height:100%;
  width:auto;
}
Palmira answered 20/1, 2013 at 6:3 Comment(0)
L
3

This did the trick for me

div img {
    width: 100%;
    min-height: 500px;
    width: 100vw;
    height: 100vh;
    object-fit: cover;
}
Lovett answered 18/11, 2016 at 16:16 Comment(0)
A
2

if you working with IMG tag, it's easy.

I made this:

<style>
        #pic{
            height: 400px;
            width: 400px;
        }
        #pic img{
            height: 225px;               
            position: relative;
            margin: 0 auto;
        }
</style>

<div id="pic"><img src="images/menu.png"></div>

$(document).ready(function(){
            $('#pic img').attr({ 'style':'height:25%; display:none; left:100px; top:100px;' })
)}

but i didn't find how to make it work with #pic { background:url(img/menu.png)} Enyone? Thanks

Ablative answered 25/3, 2013 at 17:1 Comment(1)
made a change and found an answer to my problem! nope it will help to someone. background-image: url(images/menu.png); background-repeat: no-repeat; position: absolute; background-size: 300px; height: 100%; width: 100%; and you can change value of background-size using javascript or jquery ( .attr({ 'style':'background-size:150px auto; left:50px; top:50px;' }) )Ablative
B
2

I had similar issue. I resolved it with just CSS.

Basically Object-fit: cover helps you achieve the task of maintaining the aspect ratio while positioning an image inside a div.

But the problem was Object-fit: cover was not working in IE and it was taking 100% width and 100% height and aspect ratio was distorted. In other words image zooming effect wasn't there which I was seeing in chrome.

The approach I took was to position the image inside the container with absolute and then place it right at the centre using the combination:

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Once it is in the centre, I give to the image,

// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;

// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;

This makes the image get the effect of Object-fit:cover.


Here is a demonstration of the above logic.

https://jsfiddle.net/furqan_694/s3xLe1gp/

This logic works in all browsers.

Bowrah answered 12/6, 2019 at 14:29 Comment(2)
The downside of this method is that when the real image size is smaller than it's container, the image is not expanded to fill the container.Footfall
Are you sure? Because the height:100% and/or width:100% fills the container to entire height and width respectively. If you could share a jsfiddle link, it will help understand the limitation you have in mind.Bowrah
R
1

HTML:

<style>
#foo, #bar{
    width: 50px; /* use any width or height */
    height: 50px;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
}
</style>

<div id="foo" style="background-image: url('path/to/image1.png');">
<div id="bar" style="background-image: url('path/to/image2.png');">

JSFiddle

...And if you want to set or change the image (using #foo as an example):

jQuery:

$("#foo").css("background-image", "url('path/to/image.png')");

JavaScript:

document.getElementById("foo").style.backgroundImage = "url('path/to/image.png')";
Readability answered 20/3, 2016 at 11:32 Comment(0)
N
1

Many of the solutions found here have some limitation: some not working in IE ( object-fit) or older browsers, other solutions do not scale up the images (only shrink it), many solution do not support resize of the window and many are not generic, either expect fix resolution or layout(portrait or landscape)

If using javascript and jquery is not a problem I have this solution based on the code of @Tatu Ulmanen. I fixed some issues, and added some code in case the image is loaded dinamically and not available at begining. Basically the idea is to have two different css rules and apply them when required: one when the limitation is the height, so we need to show black bars at the sides, and othe css rule when the limitation is the width, so we need to show black bars at the top/bottom.

function applyResizeCSS(){
    var $i = $('img#imageToResize');
    var $c = $i.parent();
    var i_ar = Oriwidth / Oriheight, c_ar = $c.width() / $c.height();  
    if(i_ar > c_ar){
        $i.css( "width","100%");
        $i.css( "height","auto");          
    }else{
        $i.css( "height","100%");
        $i.css( "width","auto");
    }
}   
var Oriwidth,Oriheight;
$(function() {
    $(window).resize(function() {
        applyResizeCSS();
    });

    $("#slide").load(function(){
        Oriwidth  = this.width,
        Oriheight = this.height; 
        applyResizeCSS();
    }); 

    $(window).resize();
}); 

For an HTML element like:

<img src="images/loading.gif" name="imageToResize" id="imageToResize"/> 
Nabila answered 17/10, 2018 at 9:50 Comment(0)
N
0

try this

HTML:

<div class="container"></div>

CSS:

.container{
background-image: url("...");
background-size: 100%;
background-position: center;
}
Neoterize answered 20/2, 2021 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.