Search code examples
htmlcssflexbox

Why is flexbox container wider than the image it contains?


I want to create a simple webpage with a header and image below it. It needs to meet the following specifications:

  • The sum of the header height and image height should total to the viewport height.
  • The image should maintain its aspect ratio and should not be cropped.
  • If the width of image is less than the viewport width, the image and header should be centered vertically.

Here is an example of how I want it formatted

Below is my attempt to accomplish this:

html,body,#root {
  height: 100vh;
  padding: 0;
  margin: 0;
}

.top-container {
  display: flex;
  justify-content: center;
  height: 100%;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: start;
}

.header {
  display: flex;
  background-color: yellow;
}

.header-item {
  width: 30px;
  height: 30px;
  background-color: green;
  margin: 10px;
}

.image-container {
  display: flex;
  min-height: 0;
  justify-content: flex-start;
  background-color: blue;
}

.image {
  max-width: 100%;
  min-height: 0;
  max-height: 100vh;
}
  <div class="top-container">
    <div class="container">
      <div class="header">
        <div class="header-item"></div>
        <div class="header-item"></div>
        <div class="header-item"></div>
      </div>
      <div class="image-container">
        <img class="image" src="https://wallpapers.com/images/hd/lake-side-trees-live-desktop-jwhxpov3u0jdebb0.jpg"></img>
      </div>
    </div>
  </div>

CodePen

This does everything I wanted except the image-container is wider than the image it contains. This prevents me from centering container correctly.

I suspect this is an issue with how flex containers calculate their width when they contain an image but I could be wrong. Any suggestions or insight would be appreciated.


Solution

  • You might reduce your code and have it working as desired.

    As you can see, you don't really need all those containers and wrappers as they add more complexity but not more control over the layout. Having classnames on each element does not help either (contrary to popular BEM belief).

    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    section {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      height: 100vh;
      width: fit-content;
      margin: 0 auto;
      
      header {
        display: flex;
        align-self: flex-start;
        background-color: yellow;
      
        div {
          width: 30px;
          height: 30px;
          background-color: green;
          margin: 10px;
        }
      }
      
      img {
        display: block;
        max-height: calc(100% - 50px);
        max-width: 100%;
      }
    }
    <section>
      <header>
        <div></div>
        <div></div>
        <div></div>
      </header>
      <img src="https://wallpapers.com/images/hd/lake-side-trees-live-desktop-jwhxpov3u0jdebb0.jpg">
    </section>