Make a grid item span to the last row / column in implicit grid
Is it possible to make a grid item span from the first to the last row when I don't know the number of rows?
Lets say I have the following html with an unknown number of boxes.
How can I make the third .box
span from the first grid-line to the last?
.container {
display: grid;
grid-template-columns: repeat(3, minmax(10rem, 1fr)) [last-col] 35%;
grid-template-rows: auto [last-line];
}
.box {
background-color: blue;
padding: 20px;
border: 1px solid red;
}
.box:nth-child(3) {
background-color: yellow;
grid-column: last-col / span 1;
grid-row: 1 / last-line;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box">3</div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Is it possible to make a grid item span from the first to the last row when I don't know the number of rows?
A natural Grid solution to this problem appears to be missing in the current spec (Level 1). So the answer would be "no", strictly with Grid properties.
However, as pointed out in this answer, it may be possible with absolute positioning.
While CSS Grid cannot make a grid area span all columns / rows in an implicit grid, it can do the job in an explicit grid.
Use negative integers.
Here are two interesting sections in the CSS Grid specification:
7.1. The Explicit Grid
Numeric indexes in the grid-placement properties count from the edges of the explicit grid. Positive indexes count from the start side, while negative indexes count from the end side.
and here...
8.3. Line-based Placement: the
grid-row-start
,grid-column-start
,grid-row-end
, andgrid-column-end
propertiesIf a negative integer is given, it instead counts in reverse, starting from the end edge of the explicit grid.
In other words, when dealing with an explicit grid, which is a grid that you define using these properties:
grid-template-rows
grid-template-columns
grid-template-areas
... you can make a grid area span all columns by setting this rule:
grid-column: 3 / -1;
That tells the grid area to span from the third column line to the last column line.
The reverse would be:
grid-column: 1 / -3;
Again, this method works only in explicit grids.
You can add grid-row-start to that boxes css, and set it to span an absurdly high number.
.container {
display: grid;
grid-template-columns: repeat(3, minmax(10rem, 1fr)) [last-col] 35%;
grid-template-rows: auto [last-line];
}
.box {
background-color: blue;
padding: 20px;
border: 1px solid red;
}
.box:nth-child(3) {
background-color: yellow;
grid-column: last-col / span 1;
grid-row: 1 / last-line;
grid-row-start: span 9000;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box">3</div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Edit - Disclaimer:
This is a non-optimal solution and does not work in every browser, be careful! Although this may appear to work in some browsers (Chrome), other browsers (Firefox) will create the absurd number of rows which causes problems.
A solution that actually worked for me to set position: absolute;
on the element you want to grow to the end. This will have its drawbacks but could be a life saver in some cases. Here is a full example:
.grid {
display: grid;
grid-template: auto / auto 22px auto;
position: relative;
}
.vline {
position: absolute;
height: 100%;
width: 2px;
background-color: black;
grid-column: 2 / span 1;
margin: 0 10px;
}
.grid h1:nth-child(1) { grid-row: 1; grid-column: 1; text-align: right; }
.grid p:nth-child(2) { grid-row: 2; grid-column: 1; text-align: right; }
.grid h1:nth-child(3) { grid-row: 3; grid-column: 3; }
.grid p:nth-child(4) { grid-row: 4; grid-column: 3; }
.grid h1:nth-child(5) { grid-row: 5; grid-column: 1; text-align: right; }
.grid p:nth-child(6) { grid-row: 6; grid-column: 1; text-align: right; }
.grid h1:nth-child(7) { grid-row: 7; grid-column: 3; }
.grid p:nth-child(8) { grid-row: 8; grid-column: 3; }
p, h1 { margin: 0; padding: 0; }
<div class="grid">
<h1>1.</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dui nulla, dictum sed tortor ut, tempus posuere odio.</p>
<h1>2.</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<h1>3.</h1>
<p>In dui nulla, dictum sed tortor ut, tempus posuere odio.</p>
<h1>4.</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dui nulla, dictum sed tortor ut, tempus posuere odio.</p>
<div class="vline"></div>
</div>
So if it doesn't seem possible yet, you might opt for changing the structure and nest the grid.
Use JavaScript to take out the third box and place it besides your original grid container, if you're unable to do that in advance.
.container {
display: grid;
grid-template-columns: 65% 35%;
}
.nested_grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
grid-template-rows: auto;
}
.box {
background-color: blue;
padding-bottom: 20px;
border: 1px solid red;
}
.side {
background-color: yellow;
grid-column: 1 -1;
border: 1px solid red;
}
<div class="container">
<div class="nested_grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="side">3</div>
</div>
<p><a href="gridbyexample.com">gridbyexample.com</a></p>