How can we make a margin element fill a flexbox item that is not itself a flexbox?
An element (even a nested one with margins) can easily fill its container using position: absolute
-- if it's not inside a flexbox item. Why does this not work for an element inside a flexbox item?
<main>
<nav>NAV</nav>
<section>
<div>DIV</div>
</section>
</main>
<style>
html, body {
position:absolute; top:0; left:0; right:0; bottom:0;
margin: 0;
}
main {
position:absolute; top:0; left:0; right:0; bottom:0;
display: flex;
}
nav {
flex-basis: 250px;
background-color: #eee;
}
section {
flex-basis: 100%;
background-color: #ccc;
margin: 10px;
}
div {
/* position:absolute; top:0; left:0; right:0; bottom:0; */
/* why doesn't the above line work? */
background-color: #cfc;
margin: 10px;
}
</style>
There are many similar-looking questions like this one and this one that don't really apply to items inside flexboxes or items with margin. There are loads of special-case solutions like align-self: stretch
, height: 100%
and box-sizing: border-box
that just don't work in this example because of the nested margin
or the fact that the flexboxes themselves aren't nested. The problems with these one-off hacks go on and on...
So what is the general method to fill a flexbox item? What is the issue with position:absolute
here? What is the most general way to make an element fill its container?
CodePudding user response:
<main>
<nav>NAV</nav>
<section>
<div>DIV</div>
</section>
</main>
<style>
html, body {
position:absolute; top:0; left:0; right:0; bottom:0;
margin: 0;
min-height: 100%;
}
main {
position:absolute; top:0; left:0; right:0; bottom:0;
display: flex;
min-height: 100%;
}
nav {
flex-basis: 250px;
background-color: #eee;
}
section {
flex-basis: 100%;
background-color: #ccc;
margin: 10px;
display: flex;
}
div {
/* position:absolute; top:0; left:0; right:0; bottom:0; */
/* why doesn't the above line work? */
background-color: #cfc;
margin: 10px;
flex: 1;
}
</style>
CodePudding user response:
Below is an idea you might find worth exploring? I put the nav
as a sibling of main
rather than a child. That's not necessary for the CSS but the structure makes most sense. Ideally, you have header
, nav``main
,footer
, possibly an aside
as well. You really want to avoid all that absolute positioning. It does not play well on mobile phone - imagine what happens if you put a textbox or textarea on your page and a mobile user clicks on it and the soft-keyboard pops up.
body {
display: grid;
grid-template-columns: [left] 196px [main] 1fr [right];
grid-template-rows: [top] 1fr [bottom];
grid-gap: 4px;
outline: 1px dashed #616161;
min-height: 100vh;
min-width: 0;
}
body > nav {
outline: 1px dashed red;
grid-column-start: left;
grid-column-end: main;
grid-row-start: top;
grid-row-end: bottom;
}
body > main {
outline: 1px dashed blue;
grid-column-start: main;
grid-column-end: right;
grid-row-start: top;
grid-row-end: bottom;
display: flex;
flex-flow: column nowrap;
}
section {
flex: 1 1 auto;
display: flex;
flex-flow: column nowrap;
}
div {
flex: 1 1 auto;
margin: 4px;
outline: 1px dotted green;
min-height: auto;
}
<nav>NAV</nav>
<main>
<section>
<div>DIV</div>
</section>
</main>