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>
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.
2
Answers
To do that, I’ll first grab the content container, that’s the one that wraps around everything and set its display to flex. This creates a flexible box that flexes based on the intrinsic size of its elements. And as a result we get horizontal scrolling because these images are huge.
Removing
height: 100vh;
from thehtml, body, #root
CSS ruleset in your example code seems to solve this issue.Run this update and you will see the blue background is no longer visible on your image.
SNIPPET:
Further details:
The cause is
justify-content: flex-start;
which is aligning the image to the start of the container (left hand side) so if you set this tojustify-content: center;
the blue bordering will be visible on both sides.The container box size still exceeds the image size because you’re giving the image it’s maximum width (but no default width) and a maximum height but the size ratio of the container is different from the image. You should probably look into some sort of
cover
/overflow aspect such as in this Q&A:Snippet 2:
retaining the
#root
rules: