My initial goal is
- stack images vertically within the viewport but never trigger an overflow. I deliberately don’t use 100vh but 100% to better adapt to mobiles. It does not change the game anyway.
- images should shrink if they don’t fit vertically or horizontally
- images should enlarge to fill the space
- images should not distord
I have a somewhat working codepen but I can’t understand why it requires an overflow: auto
in the child to behave the way I need.
* {
box-sizing: border-box;
}
html {
height: 100%;
}
body {
font-family: Verdana, sans-serif;
font-size: 0.8em;
height: 100%;
}
.flex-parent {
display: flex;
flex-direction: column;
color: black;
gap: 8px;
height: 100%;
}
.flex-child {
flex: 1 1 0;
align-self: center;
overflow: auto;
}
.image {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
<!DOCTYPE html>
<html>
<style>
</style>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="flex-parent">
<div class="flex-child">
<img draggable="false" class="image" src="https://dummyimage.com/600x400/0010ee/fff">
</div>
<div class="flex-child">
<img draggable="false" class="image" src="https://dummyimage.com/600x400/0010ee/fff">
</div>
</div>
</body>
</html>
Any insight is welcome. I really would like to understand what goes on here. I understand a bit that there is something about block formatting context, but don’t fully grasp it.
I tried to play with object: contain
with no success.
2
Answers
Your
flex-child
has no height defined. That’s why it calculates it’s height by combining the height of it’s child elements. In this case the child is theimg
element. Which has a css height property with the value 100%. This means 100% of the parent element. But the height of the parent element depends on the height of the child elements, so we are now in an infinite loop.That why the browser decides to calculate the height of the
img
element from the image that’s rendered in theimg
element instead. The image in theimg
element has a height of 400 pixels and thus theimg
element gets a height of 400 pixels as well.To break this infinite loop you can set
overflow: auto
(oroverflow: hidden
) on theflex-child
element.Or another way is to set
height: 100%
on theflex-child
element.That way the height of the
flex-child
element now depends on the height of the parent element instead of it’s child elements. The height of the parent element is now equally distributed between alflex-child
elements.If you don’t like
overflow: auto
, you can setmin-height
other thanauto
. Or anyoverflow
value other thanvisible
.This is necessary so that the element can shrink, because by default when
overflow: visible
– it is set tomin-height: auto
.Automatic Minimum Size of Flex Items