0

My home dashboard has a general structure of div elements piled one on top of each other (each of them is screen-wide and provides different kind of information).

I manage the height of the blocks though CSS Grid: the whole application is min-height: 100vh; and the rows are auto except for one which is 1fr. It works great.

I am now faced with the case where one of the lines is dynamically present or absent. This is because it is actually a Vue component, displayed conditionally with v-if. The problem is that the CSS part is not aware of its presence and grid-template-rows is fixed. This leads to the wrong rows being auto and 1fr when it is toggled.

How to fix that?

One way I can think of would be to force the presence of the component in a way where CSS would count it as a row. Right now I see this element as <!----> == $0 in Dev Tools when it is off.

Another one would be to "describe" the columns template rather than have a fixed list. Something along the lines of "use auto as much as possible, then 1fr and one auto"


The two code fragments below simulate my problem.

The first one is the case where all elements are visible

#app {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto auto 1fr;
}

#footer {
  align-self: end;
}

div {
  border-style: dashed;
  border-width: 1px;
}
<div id="app">
  <div>this line is always visible</div>
  <div>this one is toggled - here it is visible</div>
  <div id="footer">this is the footer</div>
</div>

The one below is the same code, but with the second line toggled (commented out here, disabled via v-if in the real code). See how it affect the footer which is not at the bottom anymore because the CSS has not changed (= did not adapt to a dissapearing row)

#app {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto auto 1fr;
}

#footer {
  align-self: end;
}

div {
  border-style: dashed;
  border-width: 1px;
}
<div id="app">
  <div>this line is always visible</div>
  <!-- <div>this one is toggled - here it is not visible anymore </div> -->
  <div id="footer">this is the footer</div>
</div>

3
  • can you share your code? so we can see the structure, the number of element, the template, etc Commented Dec 26, 2019 at 13:56
  • @TemaniAfif: OK, got an idea to minimize the code and the examples reflect my problem now. Commented Dec 26, 2019 at 14:36
  • Um...Why not use flexbox for this ? Commented Dec 26, 2019 at 17:06

2 Answers 2

1

One idea is to explicitely define the row for the footer to always use the last one:

#app {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto auto 1fr;
}

#footer {
  align-self: end;
  grid-row:-1;
}

div {
  border-style: dashed;
  border-width: 1px;
}
<div id="app">
  <div>this line is always visible</div>
  <div>this one is toggled - here it is visible</div>
  <div id="footer">this is the footer</div>
</div>

<div id="app">
  <div>this line is always visible</div>
  <!--<div>this one is toggled - here it is visible</div>-->
  <div id="footer">this is the footer</div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Ah, this is a good idea. I was looking for this kind of relative counting but did not know it existed. How are the auto in grid-template-rows interpreted then - when the amount of elements in grid-template-rows does not match the actual number of rows? (when the toggled row is off)
@WoJ the middle auto will get computed to 0 but you will always have 3 rows and the second one empty since no item is placed inside it
0

The CSS grid system isn't the best for dynamic rows/columns. It's at its best when you know what the layout will be ahead of time.

However, there some things you can do.

Option 1

You can define grid-template-rows: auto auto 1fr; using inline styles (within the parent element, and control using javascript.

So, in this case:

<div id="app" style="grid-template-rows: auto auto 1fr;">

And as the number of rows change, you alter the value of the style.

<div id="app" style="grid-template-rows: auto 1fr;">

Option 2

Define several classes ahead of time and switch to the appropriate class based on the number of rows:

.rows-2
  grid-template-rows: auto 1fr;
}

.rows-3
  grid-template-rows: auto auto 1fr;
}
<div id="app" class="rows-2/3">

Both these solutions will require some javascript to adjust to the required grid layout.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.