901

I am working with images, and I ran into a problem with aspect ratios.

<img src="big_image.jpg" width="900" height="600" alt="" />

As you can see, height and width are already specified. I added a CSS rule for images:

img {
  max-width: 500px;
}

But for big_image.jpg, I receive width=500 and height=600. How do I set images to be re-sized, whilst keeping their aspect ratios.

Radllaufer
  • 187
  • 1
  • 2
  • 10
moonvader
  • 19,761
  • 18
  • 67
  • 116

26 Answers26

1054

img {
  display: block;
  max-width:230px;
  max-height:95px;
  width: auto;
  height: auto;
}
<p>This image is originally 400x400 pixels, but should get resized by the CSS:</p>
<img width="400" height="400" src="https://i.stack.imgur.com/aEEkn.png">

This will make image shrink if it's too big for specified area (as downside, it will not enlarge image).

Flimm
  • 136,138
  • 45
  • 251
  • 267
setec
  • 15,506
  • 3
  • 36
  • 51
  • 45
    Is there a version of this that will enlarge images to fit their container also? I've tried the max-width/max-height as numbers with width/height as auto, but as setec said above, it will not enlarge the image. I've tried using min-width/min-height also. I just can't get the combination right. I simply want that whatever image I have to put into this container, it will display at it's maximum size possible without changing aspect ratio regardless of whether that involves shrinking or growing the image to achieve that. – Dee2000 Apr 14 '14 at 21:10
  • @Dee2000 i've tried all what you said too without result, looks like it's not possible with pure css (but have't yet tried css3). Finally come to use of solution described here http://stackoverflow.com/a/170636/753621, but it requires JS. – setec Apr 15 '14 at 07:03
  • I saw that one too, it didn't help me. I've now built a JS function to figure out what the right size is. Normally that would have been my default goto method, but I've been trying to use CSS more where possible. – Dee2000 Apr 15 '14 at 11:14
  • I tested the code in three browsers: Firefox, Chrome and IE11. Works perfect so far. CSS workaround is always preferred over JavaScript. Great solution... nice and easy! – Subrata Sarkar May 27 '14 at 14:46
  • 10
    Seems that display: block is no more needed. – actimel Jun 26 '14 at 09:18
  • 4
    Note that the question was about an `` that itself includes a width and height and I think that means you need to use `!important` to circumvent the tag width/height info. – Alexis Wilke Jul 18 '14 at 01:28
  • 27
    @AlexisWilke CSS rules override html attributes. `!important` is not needed. – Jargs Nov 12 '14 at 23:45
  • @ahnbizcad if this isn't working make sure your IMG has an SRC. If the IMG is given a background-image via a class this may not work. – Ghost Echo Nov 11 '15 at 18:29
  • 6
    Using it on Chrome, not working for me, even with !important – Ray Jan 02 '16 at 21:30
  • It worked for me with just 'max-width' css3 property. – Felipe Correa Mar 01 '16 at 03:04
  • 1
    I don't know why people are commenting that `display: block;` is necessary, it isn't! Try experimenting with the snippet and see. – Flimm Mar 02 '16 at 14:13
  • 1
    If it isn't working, try checking the computed styles and see if a CSS rule contradicts what you expected to see. This solution works, thanks! – DerpyNerd Jan 13 '17 at 23:39
  • 2
    I had it in a flex context with a very wide sibling and this caused the image to be shown distorted. Wrapping the `` tag in an element with `display: block` fixed it. – Günter Zöchbauer Mar 01 '18 at 21:20
  • 3
    Add `margin: auto;` if you want it centered in it's container – Omar Jun 05 '19 at 05:18
  • 1
    please note this will cause a problem with Google CLS - Cumulative Layout Shift - the size of the image and thus size of the block reserved for image to be painted in is different than CSS dimensions, and this will cause the shift :( is there a way how to work around this? – Radek Apr 12 '21 at 13:15
  • @Dee2000 use [object-fit](https://stackoverflow.com/a/39039206/4854931). You can set height in width in px if you need. – Alex78191 Jun 24 '22 at 11:57
  • Thanks @Alex78191, that page I was working on 8 years ago is almost finished, I'll try that :-) Just kidding, I don't even remember what that was for now. – Dee2000 Jun 24 '22 at 15:40
  • This didn't work for me either. The object-fit one below did however – frank Oct 03 '22 at 16:05
  • @Dee2000 have you ever found a way with pure css? – theonlygusti Feb 08 '23 at 17:24
679

Here's a solution:

object-fit: cover;
width: 100%;
height: 250px;

You can adjust the width and height to fit your needs, and the object-fit property will do the cropping for you.

More information about the possible values for the object-fit property and a compatibility table are available here: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

starball
  • 20,030
  • 7
  • 43
  • 238
Théo T. Carranza
  • 7,813
  • 1
  • 21
  • 14
298

The solutions below will allow scaling up and scaling down of the image, depending on the parent box width.

All images have a parent container with a fixed width for demonstration purposes only. In production, this will be the width of the parent box.

Best Practice (2018):

This solution tells the browser to render the image with max available width and adjust the height as a percentage of that width.

.parent {
  width: 100px;
}

img {
  display: block;
  width: 100%;
  height: auto;
}
<p>This image is originally 400x400 pixels, but should get resized by the CSS:</p>
<div class="parent">
  <img width="400" height="400" src="https://place-hold.it/400x400">
</div>

Fancier Solution:

With the fancier solution, you'll be able to crop the image regardless of its size and add a background color to compensate for the cropping.

.parent {
  width: 100px;
}

.container {
  display: block;
  width: 100%;
  height: auto;
  position: relative;
  overflow: hidden;
  padding: 34.37% 0 0 0; /* 34.37% = 100 / (w / h) = 100 / (640 / 220) */
}

.container img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
<p>This image is originally 640x220, but should get resized by the CSS:</p>
<div class="parent">
  <div class="container">
    <img width="640" height="220" src="https://place-hold.it/640x220">
  </div>
</div>

For the line specifying padding, you need to calculate the aspect ratio of the image, for example:

640px (w) = 100%
220px (h) = ?

640/220 = 2.909
100/2.909 = 34.37%

So, top padding = 34.37%.

Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
Aternus
  • 3,375
  • 1
  • 14
  • 9
  • I don't get it. I've loaded full HD images with both this and the accepted answer's solution. Is it really being scaled becasue I can't tell (tested on chrome and IE10+) – DerpyNerd Jan 13 '17 at 23:37
  • 2
    I love how standardization organizations were in a meeting once and all agreed: this should be the way people are going to achieve the desired result. – Ben Fransen Mar 23 '18 at 22:27
  • 2018 solution is bad, when the parent has width/height ratio smaller than the image width/height ratio, the image end up stretched badly. – izzulmakin Apr 24 '18 at 03:19
  • @izzulmakin How about a codepen so I can see what you're talking about? – Aternus Apr 30 '18 at 19:33
  • Neither of these work for me to upscale the image and keep the aspect ratio. – Koenigsberg Aug 01 '18 at 08:48
  • @Mär please post your code in a CodePen so I can help you out :) – Aternus Aug 01 '18 at 16:18
  • 2
    That won't make too much sense. It's a 15k lines of code web architecture. The specific code you posted will result in correct scaling for images that have lower aspect ratios than that of their parent container, but will not work if it is vice versa, resulting in stretching. I was specifically looking for a dynamic approach, as prior I do not know DIV size or image dimensions. In the end I solved this by preloading the image, calculating the aspect ratio, comparing it versus the aspect ratio of the area and then apply the proper CSS style. – Koenigsberg Aug 01 '18 at 16:23
  • You can try it yourself though, if you like. Take an image that has a *lower* aspect ratio than the container it is placed in (IMG in DIV) and apply your code selecting *width: 100%*. The result should be a stretched image. – Koenigsberg Aug 01 '18 at 16:26
  • You lost me at position: absolute – Peter Graham Aug 24 '18 at 19:11
  • I used width:auto for the parent. – Ansjovis86 Apr 30 '19 at 14:56
  • @Madeo please create a CodePen to describe your issue. On another note... I'm thankful for all the comments that made these snippets better but you need to invest some time explaining what you're trying to achive in order for me to be able to help. – Aternus May 20 '19 at 16:14
  • Your math is a bit roundabout: since you just want `h` as a percentage of `w`, then instead of a chain of divisions, you can just do `100 * h / w`. Thus `100 * 220 / 640 = 34.37`. – Théophile Sep 03 '20 at 05:36
  • @Théophile Thanks for the comment. It was meant to be informative and easy to follow along. – Aternus Dec 01 '20 at 23:24
  • The fancier solution doesn't scale images up. Here's a demonstration: https://jsfiddle.net/edmjgs58/ – Lars SG Feb 08 '21 at 00:25
  • This didn't work for me in when the parent has display: flex... but only in Safari. Adding align-items: start fixed it. – tschumann Mar 04 '21 at 06:21
  • Thanks! The fancier solution worked in my case. Also loved the calculation explained for padding. – Zeeshan Jul 19 '23 at 18:06
94

Very similar to some answers here, but in my case I had images that sometimes were taller, sometimes larger.

This style worked like a charm to make sure that all images use all available space, keep the ratio and not cuts:

.img {
   object-fit: contain;
   max-width: 100%;
   max-height: 100%;
   width: auto;
   height: auto;
}
Moisés
  • 1,324
  • 15
  • 43
77

The background-size property is ie>=9 only, but if that is fine with you, you can use a div with background-image and set background-size: contain:

div.image{
    background-image: url("your/url/here");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

Now you can just set your div size to whatever you want and not only will the image keep its aspect ratio it will also be centralized both vertically and horizontally within the div. Just don't forget to set the sizes on the css since divs don't have the width/height attribute on the tag itself.

This approach is different than setecs answer, using this the image area will be constant and defined by you (leaving empty spaces either horizontally or vertically depending on the div size and image aspect ratio), while setecs answer will get you a box that exactly the size of the scaled image (without empty spaces).

Edit: According to the MDN background-size documentation you can simulate the background-size property in IE8 using a proprietary filter declaration:

Though Internet Explorer 8 doesn't support the background-size property, it is possible to emulate some of its functionality using the non-standard -ms-filter function:

-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='path_relative_to_the_HTML_file', sizingMethod='scale')";
Hoffmann
  • 14,369
  • 16
  • 76
  • 91
  • 2
    Great solution, thanks! Also note that you can replace 'contain' by 'cover' if you want to fill the div completely and crop extra pixels that doesn't fit the ratio – mbritto Nov 02 '15 at 09:31
  • 1
    While this is a correct answer programmatically, if an image "matters" this way you have no img attributes so you are killing SEO. – fat_mike Oct 11 '18 at 14:57
31

Remove the "height" property.

<img src="big_image.jpg" width="900" alt=""/>

By specifying both you are changing the aspect ratio of the image. Just setting one will resize but preserve the aspect ratio.

Optionally, to restrict oversizings:

<img src="big_image.jpg" width="900" alt="" style="max-width:500px; height:auto; max-height:600px;"/>
el Dude
  • 5,003
  • 5
  • 28
  • 40
  • 1
    i can't do it to all images - there are many images already placed in many html files – moonvader Oct 20 '12 at 18:32
  • 2
    Ok. try img {max-width:500px; height:auto; max-height:600px;} – el Dude Oct 20 '12 at 18:40
  • 1
    Useful information like that comment should be added to your post. That way we can immediately see what you've come up with. – Bram Vanroy May 30 '13 at 13:52
  • 5
    The downside of omitting the `height` attribute in the `img` tag is that the browser cannot calculate how much space the image will take up before downloading the image. This make the page slower to render and it can lead to more "jumping". – Flimm Mar 02 '16 at 14:03
30

Firefox 71+ (2019-12-03) and Chrome 79+ (2019-12-10) support internal mapping of the width and height HTML attributes of the IMG element to the new aspect-ratio CSS property.

The calculated aspect ratio is used to reserve space for the image until it is loaded, and as long as the calculated aspect ratio is equal to the actual aspect ratio of the image, page “jump” is prevented after loading the image.

For this to work, one of the two image dimensions must be overridden via CSS to the auto value:

IMG {max-width: 100%; height: auto; }
<img src="example.png" width="1280" height="720" alt="Example" />

In the example, the aspect ratio of 16:9 (1280:720) is maintained even if the image is not yet loaded and the effective image width is less than 1280 as a result of max-width: 100%.

See also the related Firefox bug 392261.

Marat Tanalin
  • 13,927
  • 1
  • 36
  • 52
18

Here is a solution :

img {
   width: 100%;
   height: auto;
   object-fit: cover;
}

This will make sure the image always covers the entire parent (scaling down and up) and keeps the same aspect ratio.

Thomas Carlton
  • 5,344
  • 10
  • 63
  • 126
14

Just add this to your css, It will automaticly shrink and expand with keeping the original ratio.

img {
    display: block;
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
}
Mark Bax
  • 141
  • 1
  • 2
13

This is mental. Use the scale-down property - it explains itself.

Inline styling:

<img src='/nic-cage.png' style={{ maxWidth: '50%', objectFit: 'scale-down' }} />

This will stop flex from stretching it. In this case, the image would go to 50% of the width of its parent container and the height would scale down to match.

Keep it simple.

Steve
  • 4,372
  • 26
  • 37
13

Just replace the height attribute by the aspect-ratio attribute.

img {
  max-width: 500px;
  aspect-ratio: 900 / 600;
}
<img src="big_image.png" width="900"/>

The aspect-ratio attribute is not necessary, but prevent image layout shifts.

Daniel Barral
  • 3,896
  • 2
  • 35
  • 47
  • The `height` and `width` attributes are not there only for display purposes but also for performance: they tell the browser what is the size of the original image. I downvoted for this reason: removing one of these attributes shouldn’t be an appropriate solution. – bfontaine Jan 09 '22 at 11:27
  • Perfectly accepted by Chrome Lighthouse – Jaime Bula Apr 08 '22 at 17:32
  • @bfontaine if you remove the height attribute, the browser is still able to get the size of the original image, by dividing the width by the aspect-ratio. So, I believe the performance problem is solved by including the "aspect-ratio" attribute as shown in my code snippet. – Daniel Barral Apr 08 '22 at 19:47
  • @DanielBarral 1- there’s no guarantee that the aspect-ratio declared in CSS is the same as the original one. 2- the height/width attribute are parsed by the browser very early when it loads the page, before fetching the image URL. The CSS is loaded/parsed later. – bfontaine Apr 12 '22 at 09:35
9

To maintain a responsive image while still enforcing the image to have a certain aspect ratio you can do the following:

HTML:

<div class="ratio2-1">
   <img src="../image.png" alt="image">
</div>

And SCSS:

.ratio2-1 {
  overflow: hidden;
  position: relative;

  &:before {
    content: '';
    display: block;
    padding-top: 50%; // ratio 2:1
  }

  img {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
  }
}

This can be used to enforce a certain aspect ratio, regardless of the size of the image that authors upload.

Thanks to @Kseso at http://codepen.io/Kseso/pen/bfdhg. Check this URL for more ratios and a working example.

Remi
  • 4,663
  • 11
  • 49
  • 84
  • I like this as it works with circles / `border-radius`. But unfortunately, it crops the image and doesn't do so well with making a border for the image in the div as far as I've tried. – Jake Apr 08 '19 at 12:56
7

Set the CSS class of your image container tag to image-class:

<div class="image-full"></div>

and add this you your CSS stylesheet.

.image-full {
    background: url(...some image...) no-repeat;
    background-size: cover;
    background-position: center center;
}
Aleksandar Toplek
  • 2,792
  • 29
  • 44
7

I would suggest for a responsive approach the best practice would be using the Viewport units and min/max attributes as follows:

img{
  display: block;
  width: 12vw;
  height:12vw;
  max-width:100%;
  min-width:100px;
  min-height:100px;
  object-fit:contain;
}
nodws
  • 1,018
  • 14
  • 18
6

To force image that fit in a exact size, you don't need to write too many codes. It's so simple

img{
    width: 200px;
    height: auto;
    object-fit: contain; /* Fit logo in the image size */
        -o-object-fit: contain; /* Fit logo fro opera browser */
    object-position: top; /* Set logo position */
        -o-object-position: top; /* Logo position for opera browser */
    }
<img src="http://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png" alt="Logo">
aislamfaisal
  • 111
  • 1
  • 4
6

https://jsfiddle.net/sot2qgj6/3/

Here is the answer if you want to put image with fixed percentage of width, but not fixed pixel of width.

And this will be useful when dealing with different size of screen.

The tricks are

  1. Using padding-top to set the height from width.
  2. Using position: absolute to put image in the padding space.
  3. Using max-height and max-width to make sure the image will not over the parent element.
  4. using display:block and margin: auto to center the image.

I've also comment most of the tricks inside the fiddle.


I also find some other ways to make this happen. There will be no real image in html, so I personly perfer the top answer when I need "img" element in html.

simple css by using background http://jsfiddle.net/4660s79h/2/

background-image with word on top http://jsfiddle.net/4660s79h/1/

the concept to use position absolute is from here http://www.w3schools.com/howto/howto_css_aspect_ratio.asp

Choco Li
  • 139
  • 2
  • 5
  • This doesn't work if "height and width are already specified" as the original question mentions. There are times when you want to force width and height and then enlarge/shrink image according to the aspect ratio. – Design by Adrian Sep 18 '19 at 12:26
5

You can use this:

img { 
    width: 500px; 
    height: 600px; 
    object-fit: contain; 
    position: relative; 
    top: 50%; 
    transform: translateY(-50%); 
}
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
user3334941
  • 739
  • 6
  • 2
3

You can create a div like this:

<div class="image" style="background-image:url('/to/your/image')"></div>

And use this css to style it:

height: 100%;
width: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: contain; // this can also be cover
Chun Yang
  • 2,451
  • 23
  • 16
3

You can set the container to display: flex and align-items: center (other align-items values work too). Instead of align-items you can also set align-self on the image itself.

SRCP
  • 224
  • 2
  • 10
3

you can use aspect-ratio property css

.my-image {
 aspect-ratio: 1/1; // square
 aspect-ratio: 16/9; // wide screen 1080p
 aspect-ratio: 4/3;
 aspect-ratio: 2/3;
}
Lasith M
  • 48
  • 7
Hossein
  • 165
  • 2
  • 8
2

This will make image shrink if it's too big for specified area (as downside, it will not enlarge image).

The solution by setec is fine for "Shrink to Fit" in auto mode. But, to optimally EXPAND to fit in 'auto' mode, you need to first put the received image into a temp id, Check if it can be expanded in height or in width (depending upon its aspect ration v/s the aspect ratio of your display block),

$(".temp_image").attr("src","str.jpg" ).load(function() { 
    // callback to get actual size of received image 

    // define to expand image in Height 
    if(($(".temp_image").height() / $(".temp_image").width()) > display_aspect_ratio ) {
        $(".image").css('height', max_height_of_box);
        $(".image").css('width',' auto');
    } else { 
        // define to expand image in Width
        $(".image").css('width' ,max_width_of_box);
        $(".image").css('height','auto');
    }
    //Finally put the image to Completely Fill the display area while maintaining aspect ratio.
    $(".image").attr("src","str.jpg");
});

This approach is useful when received images are smaller than display box. You must save them on your server in Original Small size rather than their expanded version to fill your Bigger display Box to save on size and bandwidth.

xec
  • 17,349
  • 3
  • 46
  • 54
  • 1
    Although the question post didn't spell it out, I think OP strongly implied he/she was looking for a CSS-only solution. – Flimm Mar 02 '16 at 14:31
2

You Can use:-

transform: scaleX(1.2);

to change the width without changing height.

And

transform: scaleY(1.2);

to change the height without changing width

You can use this on images and video tags in html and css. This does not change the aspect ration also.

Ole Pannier
  • 3,208
  • 9
  • 22
  • 33
1

img {
  max-width: 80px; /* Also works with percentage value like 100% */
  height: auto;
}
<p>This image is originally 400x400 pixels, but should get resized by the CSS:</p>
<img width="400" height="400" src="https://i.stack.imgur.com/aEEkn.png">

<p>Let's say the author of the HTML deliberately wants
  the height to be half the value of the width,
  this CSS will ignore the HTML author's wishes, which may or may not be what you want:
</p>
<img width="400" height="200" src="https://i.stack.imgur.com/aEEkn.png">
Flimm
  • 136,138
  • 45
  • 251
  • 267
1

How about using a pseudo element for vertical alignment? This less code is for a carousel but i guess it works on every fixed size container. It will keep the aspect ratio and insert @gray-dark bars on top/bottom or left/write for the shortest dimension. In the meanwhile the image is centered horizontally by the text-align and vertically by the pseudo element.

    > li {
      float: left;
      overflow: hidden;
      background-color: @gray-dark;
      text-align: center;

      > a img,
      > img {
        display: inline-block;
        max-height: 100%;
        max-width: 100%;
        width: auto;
        height: auto;
        margin: auto;
        text-align: center;
      }

      // Add pseudo element for vertical alignment of inline (img)
      &:before {
        content: "";
        height: 100%;
        display: inline-block;
        vertical-align: middle;
      }
    }
Paul Bormans
  • 1,292
  • 16
  • 22
1

Fullscreen presentation:

img[data-attribute] {height: 100vh;}

Keep in mind that if the view-port height is greater than the image the image will naturally degrade relative to the difference.

John
  • 1
  • 13
  • 98
  • 177
1

If the application can have an image of any aspect ratio or resolution then you can manage height and width as in this link.

This uses Javascript and HTML

https://stackoverflow.com/a/65090175/13338731