-1

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?

personal_cloud
  • 3,943
  • 3
  • 28
  • 38
  • Have you seen this post? Find the answer with 300 upvotes: https://stackoverflow.com/questions/29467660/how-to-stretch-children-to-fill-cross-axis – Nathaniel Flick Dec 12 '22 at 02:03
  • @Nathaniel My question was originally worded "How can we make a margin element fill a flexbox item that is not itself a flexbox?" and you're essentially saying, make the non-flexbox item into a flexbox. I suppose that's acceptable: non-flexbox items seem to be too complicated when it comes to filling the container. – personal_cloud Dec 12 '22 at 02:23
  • You asked for the "So what is the general method to fill a flexbox item?" (among other things) which is what I answered. :) – Nathaniel Flick Dec 12 '22 at 20:06

2 Answers2

1

<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>
Miguel Caro
  • 280
  • 1
  • 4
  • Wow, this looks great! Just running a few more tests... – personal_cloud Dec 12 '22 at 02:06
  • @personal_cloud `flex-grow` has only effect on direct descentants of a flexbox container. Neither `html` nor `body` are defined as such, so `main { flex: 1 }` shorthand would have no effect. – Rene van der Lende Dec 12 '22 at 02:17
  • @Rene Right. I was about to suggest that the answer talk about when we can and can't use the `flex:1` solution. – personal_cloud Dec 12 '22 at 02:18
  • @Miguel This is a great answer. I would just make two small changes. (1) Get rid of the `min-height`s since they add nothing, and only create the possibility that the browser miscalculates something. (2) explain that we need to use something different at the `html` and `body` levels, since they are not flexbox items. Hence the solution to use `absolute` at the top, and `flex` for everything underneath. – personal_cloud Dec 12 '22 at 02:20
1

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>
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91