[html] Maintain image aspect ratio when changing height

Using the CSS flex box model, how can I force an image to maintain its aspect ratio?

JS Fiddle: http://jsfiddle.net/xLc2Le0k/2/

Notice that the images stretch or shrink in order to fill the width of the container. That's fine, but can we also have it stretch or shrink the height to maintain the image proportions?

HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}

This question is related to html css flexbox

The answer is


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/

Actually I found out that the container of the image tag need to have a height in order to keep the ratio of the image. for example>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

then in your html your container will wrap the tag image

<div class="container"><img src="image.jpg" alt="image" /></div>

this work for IE and other browsers


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


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;

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! */
}

I just had the same issue. Use the flex align to center your elements. You need to use align-items: center instead of align-content: center. This will maintain the aspect ratio, while align-content will not keep the aspect ratio.


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

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

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

_x000D_
_x000D_
.slider {_x000D_
  display: table;_x000D_
  width: 100%;_x000D_
  table-layout: fixed;_x000D_
  border-collapse: collapse;_x000D_
}_x000D_
_x000D_
.slider>div {_x000D_
  display: table-cell;_x000D_
  vertical-align: top;_x000D_
}_x000D_
_x000D_
.slider>div>img {_x000D_
  max-width: 100%;_x000D_
  height: auto;_x000D_
}
_x000D_
<div class="slider">_x000D_
  <div><img src="https://picsum.photos/400/300?image=0" /></div>_x000D_
  <div><img src="https://picsum.photos/400/300?image=1" /></div>_x000D_
  <div><img src="https://picsum.photos/400/300?image=2" /></div>_x000D_
  <div><img src="https://picsum.photos/400/300?image=3" /></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Declare where display: flex; was given Element.
align-items: center;


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to flexbox

Force flex item to span full row width vuetify center items into v-flex Equal height rows in CSS Grid Layout display: flex not working on Internet Explorer Center the content inside a column in Bootstrap 4 Vertical Align Center in Bootstrap 4 How to use zIndex in react-native Bootstrap 4 align navbar items to the right Does 'position: absolute' conflict with Flexbox? Make flex items take content width, not width of parent container