How to maintain item height in a dynamic layout?
Asked Answered
V

1

1

I have a website, which usually contains four elements:

<section>
    <div>Div 1</div>
    <div>Div 2 - I am optional!</div>
    <div>Div 3 - I might need to grow</div>
    <div>Div 4</div>
</section>

In the mobile version of my website, all four divs are stacked on top of each other with this CSS:

section {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: min-content min-content 1fr min-content;
    row-gap: 1.5em;
}

This also produces a row-gap between each of the divs.

Problem

It might happen, that Div 2 is completely empty. In this case, Div 2 is hidden with display: none;. It should then not take up any space and also not be visible in any way.

However, with Div 2 missing, there now only are three elements and not four inside section. grid-template-rows is now treating divs 3 and 4 as if they were divs 2 and 3: They are getting the wrong height and now there is a gap under the very last div, under Div 4. That is the gap in front of the following div.

The reason is that there actually only are three divs now and not four. So Div 4 is at the position of Div 3 - which also gives it the wrong height of 1fr.

What I want

Div 3 should always be the one with the height 1fr - also when it in fact is the second element. Div 4 should always be the last element - also if that means it in fact is element number 3 and not 4.

With other words:

I want to treat one div as optional. Should that div not be there, its complete row should get taken out of the grid.

How can I get this result?

Vicereine answered 15/3, 2023 at 19:52 Comment(2)
Frankly this sounds like a job for flexboxAcervate
Oh, you are right. All my elements should be stacked one on another, being stacked only in one dimension. I obviously don't need a grid to do that. I'll try flexbox with flex-direction: column;.Vicereine
M
0

I don't see how this layout can work in Grid Level 1.

The reason being that row heights are set at the container level and can't be adjusted at the item level.

However, this problem is solved in flexbox, because there are no fixed rows or columns, and item heights can be adjusted at the item level.

The key here is knowing that div 3, whether in row 3 or 2, is always the second from last.

section {
  display: flex;
  flex-direction: column;
  row-gap: 1em;
}

div {
  flex: 0 0 min-content;
}

div:nth-last-child(2) {
  background-color: yellow;
  flex: 1;
}

/* demo styles */
section { height: 80vh; padding: 1em; }
div { background-color: aqua; }
body, h2 { margin: 0; }
<h2>Four Divs</h2>
<section>
  <div>Div 1</div>
  <div>Div 2 - I am optional!</div>
  <div>Div 3 - I might need to grow</div>
  <div>Div 4</div>
</section>

<hr>

<h2>Three Divs</h2>
<section>
  <div>Div 1</div>
  <div style="display: none">Div 2 - I am optional!</div>  
  <div>Div 3 - I might need to grow</div>
  <div>Div 4</div>
</section>
Midwife answered 16/3, 2023 at 0:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.