Make a grid item span to the last row / column in implicit grid
Asked Answered
L

5

70

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?

Let’s say I have the following HTML content 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>
Landri answered 18/5, 2017 at 15:45 Comment(1)
It's really stupid that this basic requirement can't be achieved in a brand new feature of CSS.Hydria
M
27

You can add grid-row-start to that box's CSS content, 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>

This is a non-optimal solution and does not work in every browser, so 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.

Moyers answered 18/5, 2017 at 15:55 Comment(7)
imo chomes handles this correct while firefox does not. makes no sense to create those rows if there is no content.... sadly there is no "magic" name for the last row (like :last-child)Landri
IMO doing what you asked (as FF does) is the correct behavior, even if it messes up the hack. If I had some use for two columns via css, I don't want the Chrome to not create them because the columns are empty. Of course, CSS-grid should be fixed to allow this without a hack.Bernicebernie
Seems like Firefox no longer creates the absurd number of rows (or at least columns, which was my need/test). At least, it doesn't report them in its grid debugger.Seljuk
How could you achieve this so the first item of the grid expands as a full height column at the begining of the grid? Like this i.imgur.com/UgdYrYx.pngStipule
@George, might be wrong as I did a quick 60 second hack but, update the selector from nth-child to first-child, and update grid-column to 1?Moyers
I know it's a hack, but in practical terms, what problems are caused by "the absurd number of rows"? I see them in Firefox grid debugger, but in my case they don't seem to cause any layout issues. Shall I worry about performance or something else?Bil
Chrome seems to be rendering those rows to me. There's a massive amount of space under my grid now where my line I'm trying to span all the rows for just keeps going. So something changed, perhaps.Samaveda
G
40

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, and grid-column-end properties

If 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.

Glaucoma answered 18/5, 2017 at 16:49 Comment(7)
i do not understand the explicit/implicit part... please explain what that meansLandri
The explicit grid are the rows and columns you define using the grid-template-* properties on the container. The implicit grid are the rows and columns automatically generated by the container to accommodate grid items that are positioned outside of the explicit grid.Glaucoma
negative integers for grid-row do not work for me either in any browser.Botanize
This answer is not valid. You would have to know the amount of rows to explicitly define in order for -1 to work. The original questions is about implicit rows as well.Enabling
@JasonTFeatheringham, your point is already covered in my answer. Not sure how you missed that section. It's right at the top.Glaucoma
The key word here is explicit grid. This trick won't work in implicit grid. Writing here again to remind myself and anyone reading this.Cordwood
To my suprise, FireFox rendered grid-column 1 / 999; correctly in an implicit grid and doesn't seem to generate 998 unused rowsBedcover
M
27

You can add grid-row-start to that box's CSS content, 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>

This is a non-optimal solution and does not work in every browser, so 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.

Moyers answered 18/5, 2017 at 15:55 Comment(7)
imo chomes handles this correct while firefox does not. makes no sense to create those rows if there is no content.... sadly there is no "magic" name for the last row (like :last-child)Landri
IMO doing what you asked (as FF does) is the correct behavior, even if it messes up the hack. If I had some use for two columns via css, I don't want the Chrome to not create them because the columns are empty. Of course, CSS-grid should be fixed to allow this without a hack.Bernicebernie
Seems like Firefox no longer creates the absurd number of rows (or at least columns, which was my need/test). At least, it doesn't report them in its grid debugger.Seljuk
How could you achieve this so the first item of the grid expands as a full height column at the begining of the grid? Like this i.imgur.com/UgdYrYx.pngStipule
@George, might be wrong as I did a quick 60 second hack but, update the selector from nth-child to first-child, and update grid-column to 1?Moyers
I know it's a hack, but in practical terms, what problems are caused by "the absurd number of rows"? I see them in Firefox grid debugger, but in my case they don't seem to cause any layout issues. Shall I worry about performance or something else?Bil
Chrome seems to be rendering those rows to me. There's a massive amount of space under my grid now where my line I'm trying to span all the rows for just keeps going. So something changed, perhaps.Samaveda
P
8

A solution that actually worked for me was to set position: absolute; on the element you wanted to grow to the end. This will have its drawbacks, but it could be a lifesaver 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>
Poll answered 3/5, 2018 at 18:3 Comment(0)
C
3

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>
Cupo answered 9/7, 2018 at 8:48 Comment(0)
C
-2

For those here in 2022:

The OP states they are using an implicit grid in the question title but in their code example they are defining their grid with: grid-template-columns and grid-template-rows which are defined as explicit grid properties by w3.org.

That being said, here is a solution for spanning n number of rows.

(Or columns if desired, simply replace rows with columns as necessary)

As mentioned above you are able to simply set grid-column-end: -1 on the grid item to achieve full column spanning. Earlier answers made this a little convoluted and possibly over complicated in their examples.

Grid item that you want to span all rows:

#item {
  grid-row-start: 1;
  grid-row-end: -1;
}

Here's a working code snippet:

#grid {
  height: 200px;
  width: 200px;
  display: grid;
  gap: 10px;
  grid-template: repeat(4, 1fr) / repeat(2, 1fr);
  grid-auto-flow: row dense;
}


#item1 {
  background-color: lime;
}

#item2 {
  background-color: yellow;
}

#item3 {
  background-color: blue;
}

/* Here’s the magic: */
#item4 {
  grid-row-start: 1;
  grid-row-end: -1;
  background-color: red;
}

#item5 {
  background-color: aqua;
}
<div id="grid">
  <div id="item1">1</div>
  <div id="item2">2</div>
  <div id="item3">3</div>
  <div id="item4">4 (full span)</div>
  <div id="item5">5</div>
</div>
Cathiecathleen answered 20/7, 2022 at 18:23 Comment(1)
This doesn't answer the question. Your template explicitly states the number of rows and columns, while OP says that the number of rows is not known.Unbent

© 2022 - 2024 — McMap. All rights reserved.