Search code examples
htmlcssflexboxcss-grid

How to mix grid and flex and grow one of the flex elements?


My home dashboard is made up of independent components. The components themselves, inside, are of different nature: some are managed by a CSS Grid, some by a CSS Flexbox, some are default blocks.

I would like to force the arrangements of these components so that they are stacked, and that one of them takes all available space.

The design so far

Up to now I had a justify-content: space-around; on the most exterior element (the general application container) and my components were aligned as expected:

.border {
  margin: 2px;
  border-style: dashed;
  border-width: 2px;
}

.boxofelements {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  width: 200px;
}

.element {
  width: 50px;
}

.bigbox {
  display: flex;
  flex-direction: column;
  height: 200px;
  justify-content: space-around;
}
<div class="bigbox border">
  <div class="boxofelements border">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>

  <div class="boxofelements border">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>

  <div class="boxofelements border">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>
</div>

Changes I wanted to make

I then wanted to change the stack and have the middle box take all available space below itself. Something along the lines of

enter image description here

To do so I removed the justify-content: space-around; element and tried to forcefully grow the middle element:

.border {
  margin: 2px;
  border-style: dashed;
  border-width: 2px;
}

.boxofelements {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  width: 200px;
}

.element {
  width: 50px;
}

.bigbox {
  display: flex;
  flex-direction: column;
  height: 200px;
  /* no more space around
    justify-content: space-around;
  */
}
<div class="bigbox border">
  <div class="boxofelements border">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>

  <div class="boxofelements border" style="grow: 1">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>

  <div class="boxofelements border">
    <div class="element border">one</div>
    <div class="element border">two</div>
    <div class="element border">three</div>
  </div>
</div>

And, well, nothing happened.

What is the correct incantation to say "make it so that element takes all available space in the axis, "behind" its border"? (which in my case means "below" and would mean "on the right" if the axis was on the row)


Solution

  • maybe flex-grow is what you are looking for.

    .border {
      margin: 2px;
      border-style: dashed;
      border-width: 2px;
    }
    
    .boxofelements {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      width: 200px;
    }
    
    .element {
      width: 50px;
    }
    
    .bigbox {
      display: flex;
      flex-direction: column;
      height: 200px;
      /* no more space around
        justify-content: space-around;
      */
    }
    <div class="bigbox border">
      <div class="boxofelements border">
        <div class="element border">one</div>
        <div class="element border">two</div>
        <div class="element border">three</div>
      </div>
    
      <div class="boxofelements border" style="flex-grow: 1;">
        <div class="element border">one</div>
        <div class="element border">two</div>
        <div class="element border">three</div>
      </div>
    
      <div class="boxofelements border">
        <div class="element border">one</div>
        <div class="element border">two</div>
        <div class="element border">three</div>
      </div>
    </div>