4

I have a question related to grid-row and span in the below code:

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.item {
  padding: 3rem;
  border: 1px solid #ccc;
  background: #f4f4f4;
  font-size: 1.3rem;
  font-weight: bold;
  text-align: center;
}

.item:first-child {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
  background: blueviolet;
}

.item:nth-child(9) {
  grid-column: 2 / span 3;
  grid-row: 2 / span 2;
  background: red;
}
<div class="grid">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  <div class="item">Item 8</div>
  <div class="item">Item 9</div>
  <div class="item">Item 10</div>
  <div class="item">Item 11</div>
  <div class="item">Item 12</div>
  <div class="item">Item 13</div>
  <div class="item">Item 14</div>
  <div class="item">Item 15</div>
</div>

Here's the output?:

enter image description here

As we can see in the output screenshot, Item1 spans just 1 row and item 9 spans only 1 row, but in the CSS style I have provided a row span of 2 for both item1 and item9. Can someone please explain the reason?

TylerH
  • 20,799
  • 66
  • 75
  • 101

2 Answers2

4

A bit of background first.

You have no explicit rows defined. All rows in your grid are implicit.

From the spec:

§ 7.1. The Explicit Grid

The three properties grid-template-rows, grid-template-columns, and grid-template-areas together define the explicit grid of a grid container.

In other words, because you're not using grid-template-rows or grid-template-areas, the grid has no defined rows (i.e., explicit rows), and rows are created as needed (i.e., implicit rows).

Continuing from the spec section above:

The final grid may end up larger due to grid items placed outside the explicit grid; in this case implicit tracks will be created, these implicit tracks will be sized by the grid-auto-rows and grid-auto-columns properties.

Okay, but why isn't the span 2 expanding the grid area across two rows?

Actually, it is.


Answer

The grid spec has a rule that instructs the browser to always create one grid line in the relevant axis when grid-template-columns, grid-template-rows and grid-template-areas are not present.

Again from section 7.1. above:

If these properties don’t define any explicit tracks the explicit grid still contains one grid line in each axis.

Hence, a close look at your grid (in this case, using Firefox's Inspector tool) will reveal that span 2 is working fine, but there's an extra line that has been created, so it only appears to be failing.

enter image description here

Notice how row lines 2 and 3 are superimposed.

An easy fix would be to define a height for the implicit rows. This overrides the default auto height, which causes the row to fully collapse when empty.

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 50px; /* new */
}

.item {
  padding: 3rem;
  border: 1px solid #ccc;
  background: #f4f4f4;
  font-size: 1.3rem;
  font-weight: bold;
  text-align: center;
}

.item:first-child {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
  background: blueviolet;
}

.item:nth-child(9) {
  grid-column: 2 / span 3;
  grid-row: 2 / span 2;
  background: red;
}
<div class="grid">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  <div class="item">Item 8</div>
  <div class="item">Item 9</div>
  <div class="item">Item 10</div>
  <div class="item">Item 11</div>
  <div class="item">Item 12</div>
  <div class="item">Item 13</div>
  <div class="item">Item 14</div>
  <div class="item">Item 15</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • I would add that `grid-auto-rows: 1fr` is probably the exact value the OP is looking for. – Temani Afif Feb 06 '20 at 19:39
  • @TemaniAfif, I would agree, if there was a defined height on the container. But I generally avoid using free-space distribution when there isn't any free space. That's not to say your solution wouldn't work in this case. – Michael Benjamin Feb 06 '20 at 20:26
  • (Also, I did see your note about [contributing to this post](https://stackoverflow.com/q/59919727/3597276). I haven't yet had the time to go through it carefully. I'll hopefully get to it soon.) – Michael Benjamin Feb 06 '20 at 20:27
  • 1
    True but I suspect the OP want to have equal row height so `1fr` will do the job here (no rush for the other question ;) ) – Temani Afif Feb 06 '20 at 20:59
1

In your .grid styles block, you will need to include an explicit grid-template-rows style declaration.

Once .grid explicitly contains more than one row, your styling for Item 1 and Item 9 will work.

e.g.

grid-template-rows: 1fr 1fr;

or, as @Paulie_D suggests:

grid-template-rows: minmax(0, 1fr);

Working Example:

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 1fr 1fr;
}

.item {
  padding: 3rem;
  border: 1px solid #ccc;
  background: #f4f4f4;
  font-size: 1.3rem;
  font-weight: bold;
  text-align: center;
}

.item:first-child {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
  background: blueviolet;
}

.item:nth-child(9) {
  grid-column: 2 / span 3;
  grid-row: 2 / span 2;
  background: red;
}
<div class="grid">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  <div class="item">Item 8</div>
  <div class="item">Item 9</div>
  <div class="item">Item 10</div>
  <div class="item">Item 11</div>
  <div class="item">Item 12</div>
  <div class="item">Item 13</div>
  <div class="item">Item 14</div>
  <div class="item">Item 15</div>
</div>
Rounin
  • 27,134
  • 9
  • 83
  • 108