An initial setting of a flex container is align-items: stretch
.
That means that flex items will expand across the cross axis of the container.
In a row-direction container, like in the question, the cross axis is vertical.
That means the items (images, in this case) will cover the full height of the container.
However, when a flex item has a defined cross size, that overrides the stretch
default.
From the spec:
8.3. Cross-axis Alignment: the align-items
and align-self
properties
Flex items can be aligned in the cross axis of the current line of the
flex container, similar to justify-content
but in the perpendicular
direction.
stretch
If the cross size property of the flex item computes to auto
, and
neither of the cross-axis margins are auto
, the flex item is
stretched.
This is the key language:
If the cross size property of the flex item computes to auto
And this is how the spec defines "cross size property":
The width or height of a flex item, whichever is in the cross
dimension, is the item’s cross size. The cross size property is
whichever of width
or height
that is in the cross dimension.
https://www.w3.org/TR/css-flexbox-1/#cross-size-property
So your code appears to be playing out as defined in the spec.
This is what you have:
.flex-parent {
display: flex;
max-height: 10vh;
}
<div class="flex-parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
The first image has no defined width (main size) or height (cross size), either in the CSS or the HTML. Its cross size, therefore, computes to auto
.
This statement:
If the cross size property of the flex item computes to auto
... is true, and align-items: stretch
goes into effect.
The image expands across the height of the container, which is 10px.
The second image, however, has explicit sizing. The cross size is defined in the HTML (height="240"
).
Now this statement:
If the cross size property of the flex item computes to auto
... is false, and align-items: stretch
is overridden. The HTML height
attribute prevails.
Two notes about the second image:
- The image ignores the
max-height
limit on the container because an initial setting in CSS is overflow: visible
.
- The HTML
width
and height
attributes map to their respective CSS properties. Hence, height="240"
overrides the height: auto
default. See below for the spec references.*
There are two other issues to consider when rendering images in a flex container.
The default minimum size of flex items. This setting prevents flex items from shrinking below the size of their content. Read this post for full details:
Varying behavior among major browsers. Firefox, Chrome, Safari, Edge and IE11 don't always render images as flex items in the same way. Read this post for more details:
Considering all factors above, here's my suggested solution:
.flex-parent {
display: flex;
max-height: 50vh; /* adjusted for demo */
}
.flex-parent {
min-width: 0;
}
img {
width: 100%;
height: auto;
}
<div class="flex-parent">
<div>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
<div>
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
</div>
*The HTML width
and height
attributes map to their respective CSS properties. Hence, when specified, they override the CSS defaults. From the HTML5 spec:
10.4.3 Attributes for embedded content and
images
The width
and height
attributes on applet
, embed
, iframe
,
object
or video
elements, and input
elements with a type
attribute in the Image Button state and that either represents an
image or that the user expects will eventually represent an image,
map to the dimension properties width
and height
on the element respectively.
10.2 The CSS user agent style sheet and presentational
hints
When the text below says that an attribute on an element maps to the
dimension property (or properties), it means that if the element has
an attribute set, and parsing that attribute's value using the rules
for parsing dimension
values doesn't generate an error, then the user agent is expected to use the
parsed dimension as the value for a presentational hint for
properties, with the value given as a pixel length if the dimension
was an integer, and with the value given as a percentage if the
dimension was a percentage.