In the example below, on the desktop view, there's extra space at the bottom of the .main-content element that I'd like to remove. I have a feeling that it is related to height: 100% and flex-basis but not sure. flex-shrink doesn't work, and even if it did it might mess with the layout.
Could someone please explain how the browser is interpreting this layout and creating the extra space.
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
margin: 0;
}
main {
flex-grow: 1;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
}
header,
footer,
[class^="sidebar-"],
.main-content {
box-sizing: border-box;
padding: 1rem;
}
header,
footer {
background-color: lightgreen;
}
.sidebar-nav {
background-color: lightblue;
}
.sidebar-content {
background-color: lightyellow;
}
.sidebar-right {
background-color: lightpink;
}
.main-content {
background-color: lightgray;
}
@media( min-width: 48em) {
.sidebar-nav,
.sidebar-content {
width: 26%;
margin-right: 8%;
}
.main-content,
.sidebar-right {
flex-basis: 100%;
}
.main-content {
width: 66%;
}
.sidebar-right {
margin-left: 2rem;
width: 20%;
}
.sidebar-right+.main-content {
width: calc( 66% - ( 20% + 2rem));
}
}
/* Ordering of Page Layout */
.sidebar-nav {
order: 1;
}
.main-content {
order: 2;
}
.sidebar-content {
order: 3;
}
.sidebar-right {
order: 4;
}
@media( min-width: 48em) {
.sidebar-content {
order: 2;
}
.main-content {
order: 3;
}
}
<header>
Header
</header>
<main>
<div class="container">
<div class="sidebar-nav">
Sidebar Navigation
</div>
<div class="sidebar-content">
Sidebar Content
</div>
<div class="sidebar-right">
Right Sidebar
</div>
<div class="main-content">
Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content
</div>
</div>
</main>
<footer>
Footer
</footer>
Add min-height: 0 or overflow: auto (they're mostly the same) to main and .main-content.
main {
flex-grow: 1;
min-height: 0; /* new */
}
.main-content {
order: 2;
overflow: auto; /* new */
}
Tested on Chrome, Firefox and Edge.
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
}
main {
flex-grow: 1;
min-height: 0; /* new */
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
}
header,
footer,
[class^="sidebar-"],
.main-content {
box-sizing: border-box;
padding: 1rem;
}
header,
footer {
background-color: lightgreen;
}
.sidebar-nav {
background-color: lightblue;
}
.sidebar-content {
background-color: lightyellow;
}
.sidebar-right {
background-color: lightpink;
}
.main-content {
background-color: lightgray;
}
@media(min-width: 48em) {
.sidebar-nav,
.sidebar-content {
width: 26%;
margin-right: 8%;
}
.main-content,
.sidebar-right {
flex-basis: 100%;
}
.main-content {
width: 66%;
}
.sidebar-right {
margin-left: 2rem;
width: 20%;
}
.sidebar-right+.main-content {
width: calc(66% - (20% + 2rem));
}
}
/* Ordering of Page Layout */
.sidebar-nav {
order: 1;
}
.main-content {
order: 2;
overflow: auto; /* new */
}
.sidebar-content {
order: 3;
}
.sidebar-right {
order: 4;
}
@media(min-width: 48em) {
.sidebar-content {
order: 2;
}
.main-content {
order: 3;
}
}
<header>
Header
</header>
<main>
<div class="container">
<div class="sidebar-nav">
Sidebar Navigation
</div>
<div class="sidebar-content">
Sidebar Content
</div>
<div class="sidebar-right">
Right Sidebar
</div>
<div class="main-content">
Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content<br> Main Content
</div>
</div>
</main>
<footer>
Footer
</footer>
A flex item cannot be smaller than the size of its content along the main axis. A default setting for flex items in flex-direction: column is min-height: auto. You can override this with min-height: 0 or, if you want scroll bars, overflow: auto.
Full explanation here: Why don't flex items shrink past content size?
Per the spec, for a percentage height to work as intended, it must have a defined height on the parent. For example, your .container element has this CSS:
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
}
However, the parent of .container, which is main, has no defined height.
main {
flex-grow: 1;
}
This leads to inconsistent and unreliable behavior across browsers.
Without a defined height on the parent the browser should, according to the spec, render the element with height: auto, the default setting.
However, in reality, different browsers have different rendering behavior. Some stick to the spec. Others try to guess what the author intended (which is known as an intervention).
Also, some browsers nowadays accept flex lengths on parents as adequate references for children with percentage heights. It's inconsistent and unreliable, however.
The best way to handle this set-up is to make sure to set a height on the parent so that the child with a percentage height has a clear reference point. And also make sure to use the height property, as flex-basis isn't always reliable in some browsers / situations.
Full explanation here: Chrome / Safari not filling 100% height of flex parent
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With