skip to Main Content

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.

Codepen

* {
    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


  1. 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 the img 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 the img element instead. The image in the img element has a height of 400 pixels and thus the img element gets a height of 400 pixels as well.

    To break this infinite loop you can set overflow: auto (or overflow: hidden) on the flex-child element.
    Or another way is to set height: 100% on the flex-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 al flex-child elements.

    Login or Signup to reply.
  2. If you don’t like overflow: auto, you can set min-height other than auto. Or any overflow value other than visible.
    This is necessary so that the element can shrink, because by default when overflow: visible – it is set to min-height: auto.
    Automatic Minimum Size of Flex Items

    * {
        box-sizing: border-box;
    }
    
    html {
        height: 100%;
    }
    
    body {
    
        font-family: Verdana, sans-serif;
        font-size: 0.8em;
    
        height: 100%;
        margin: 0;
    }
    
    
    
    .flex-parent {
        display: flex;
        flex-direction: column;
        color: black;
        gap: 8px;
        height: 100%;
    
    }
    
    .flex-child {
        flex: 1 1 0;
        align-self: center;
        /* 👇 */
       /* overflow: auto; */
       min-height: 0;
    }
    
    .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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search