I want to achieve a pretty simple layout using a css grid (not flexbox) :
Currently I have this (similar but with an unwanted empty white area):
My question is what is the missing part(s) in my exemple code to achieve the desired layout ?
The issue seems very similar to this question: How to make CSS Grid items take up remaining space?
And this one: How do you collapse unused row in a CSS grid?
I have a green div on the last row, this last row need to grow with the page height.
To do that the row template for this last row is set to 1fr
.
You can check the very simple code snippet below:
html {
height: 100%;
}
body {
height: 100vh;
}
.container {
display: grid;
grid-template-columns: 180px 1fr;
grid-template-rows: min-content auto 1fr;
height:100%;
}
.red-cube {
background-color: red;
width: 100%;
Height: 180px;
grid-column: 1;
grid-row: 1 / 3;
}
h1, h2 {
margin: 0;
padding: 0;
}
.blue-title {
background-color: blue;
grid-column: 2;
grid-row: 1;
height: fit-content;
}
.yellow-div {
background-color: yellow;
grid-column: 2;
grid-row: 2;
height: 100%;
}
.green-content {
background-color: green;
grid-column: 1 / 3;
grid-row: 3;
align-self: stretch;
}
<div class="container">
<div class="red-cube"></div>
<h1 class="blue-title">Title</h1>
<div class="yellow-div"><h2>Second line</h2></div>
<div class="green-content"><p>Some text</p></div>
</div>
Or play with the snippet on Codepen here.
I tested the solution of setting the grid-template-rows
value of the yellow row to 1fr
to consume the free space remaining. (the solution of the Stackoverflow question I mentioned before)
i.e. Replacing grid-template-rows: min-content auto 1fr;
with grid-template-rows: min-content 1fr 1fr;
But this will break the green div that need to grow with the page height because we will have two rows with a setting of 1fr
.
I wonder if there is a solution without switching to flexbox or creating multiple grid layout (reorganize the layout).
I also don't want to "hardcode" the row height by putting something like :
grid-template-rows: 1.25rem auto 1fr;
After lot of tests, I found a way to achieve the result I wanted without touching the HTML layout.
To force the grid algorithm to consume the free space available in the second row it's currently required to use a row height in fractional unit (fr
).
So in the CSS I added a row with a height of 0fr
(YES, 0 fraction is considered valid and trigger the grid algorithm).
0fr
row).Code snippet:
html {
height: 100%;
}
body {
height: 100vh;
}
.container {
display: grid;
grid-template-columns: 180px 1fr;
grid-template-rows: min-content auto 0fr 1fr;
height:100%;
}
.red-cube {
background-color: red;
width: 100%;
Height: 180px;
grid-column: 1;
grid-row: 1 / 3;
}
h1, h2 {
margin: 0;
padding: 0;
}
.blue-title {
background-color: blue;
grid-column: 2;
grid-row: 1;
height: fit-content;
}
.yellow-div {
background-color: yellow;
grid-column: 2;
grid-row: 2 / 4;
height: 100%;
}
.green-content {
background-color: green;
grid-column: 1 / 3;
grid-row: 4;
align-self: stretch;
}
<div class="container">
<div class="red-cube"></div>
<h1 class="blue-title">Title</h1>
<div class="yellow-div"><h2>Second line</h2></div>
<div class="green-content"><p>Some text</p></div>
</div>
I tested this solution on Chrome, Firefox & Safari and they all give the wanted result ;)
You can also play with this Codepen version: https://codepen.io/BSO__/pen/wvrEBWx