Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain image aspect ratio when changing height

Tags:

html

css

flexbox

People also ask

How do I preserve an image aspect ratio?

The Simple Solution Using CSSBy setting the width property to 100%, you are telling the image to take up all the horizontal space that is available. With the height property set to auto, your image's height changes proportionally with the width to ensure the aspect ratio is maintained.

How do you keep proportions when resizing?

While Constrain Proportions is enabled, when you resize the shape, it will won't stretch the shape, but keep the height and width in the shape's original proportions. Select the shape or shapes you want to constrain. Select the Arrange tab in the format panel on the right. Select the Constrain Proportions checkbox.

Why you should maintain the aspect ratio while resizing an image?

When scaling your image, it's crucial to maintain the ratio of width to height, known as aspect ratio, so it doesn't end up stretched or warped. If you need a specific width and height, you may need a mixture of resizing and cropping to get the desired result.

How do I resize an image without changing the aspect ratio in CSS?

In that situation we can use CSS max-width or width to fit the image. Use max-width: 100% to limit the size but allow smaller image sizes, use width: 100% to always scale the image to fit the parent container width.


To keep images from stretching in either axis inside a flex parent I have found a couple of solutions.

You can try using object-fit on the image which, e.g.

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Or you can add flex-specfic rules which may work better in some cases.

align-self: center;
flex: 0 0 auto;

For img tags if you define one side then other side is resized to keep aspect ratio and by default images expand to their original size.

Using this fact if you wrap each img tag into div tag and set its width to 100% of parent div then height will be according to aspect ratio as you wanted.

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}

No need to add a containing div.

The default for the css "align-items" property is "stretch" which is what is causing your images to be stretched to its full original height. Setting the css "align-items" property to "flex-start" fixes your issue.

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}

Most of images with intrinsic dimensions, that is a natural size, like a jpeg image. If the specified size defines one of both the width and the height, the missing value is determined using the intrinsic ratio... - see MDN.

But that doesn't work as expected if the images that are being set as direct flex items with the current Flexible Box Layout Module Level 1, as far as I know.

See these discussions and bug reports might be related:

  • Flexbugs #14 - Chrome/Flexbox Intrinsic Sizing not implemented correctly.
  • Firefox Bug 972595 - Flex containers should use "flex-basis" instead of "width" for computing intrinsic widths of flex items
  • Chromium Issue 249112 - In Flexbox, allow intrinsic aspect ratios to inform the main-size calculation.

As a workaround, you could wrap each <img> with a <div> or a <span>, or so.

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5 Implied Minimum Size of Flex Items

To provide a more reasonable default minimum size for flex items, this specification introduces a new auto value as the initial value of the min-width and min-height properties defined in CSS 2.1.


Alternatively, you can use CSS table layout instead, which you'll get similar results as flexbox, it will work on more browsers, even for IE8.

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

I have been playing around flexbox lately and i came to solution for this through experimentation and the following reasoning. However, in reality I'm not sure if this is exactly what happens.

If real width is affected by flex system. So after width of elements hit max width of parent they extra width set in css is ignored. Then it's safe to set width to 100%.

Since height of img tag is derived from image itself then setting height to 0% could do something. (this is where i am unclear as to what...but it made sense to me that it should fix it)

DEMO

(remember saw it here first!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

Works only in chrome yet


This behavior is expected. flex container will stretch all its children by default. Image have no exception. (ie, parent will have align-items: stretch property )

To keep the aspect ratio we've two solutions:

  1. Either replace default align-items: stretch property to align-items: flex-start or align-self: center etc, http://jsfiddle.net/e394Lqnt/3/

or

  1. Set align property exclusively to the child itself: like, align-self: center or align-self: flex-start etc. http://jsfiddle.net/e394Lqnt/2/