2

This question is about whether CSS grid "span counting" -- whether it should start on implicit grid line. In CSS Definitive Guide, 4th Ed, p. 695, it is said that

box4 is where things really get interesting. It ends on the fifth row line, which is to say the second implicit grid line. It spans back three lines—and yet, it still starts on the same grid line as box3. This happens because spans have to start counting within the explicit grid. Once they start, they can continue on into the implicit grid (as happened with box2), but they cannot start counting within the implicit grid.

Is it true? Or has there been a spec change? Can "span counting" start within implicit grid?

It is a bit confusing as the code in the book used:

.box04 {grid-column: 4; grid-row: span 2 / 5;}

while the online code on Github.com used:

.box04 {grid-column: 4; grid-row: span 4 / 5;}

(so I do see it start counting at row grid line 5, and start counting 4 steps back starting at this implicit grid line 5, and the rule is "we shouldn't start counting at implicit grid lines". So has the rule changed or the rule doesn't mean it that way?).

and in order to have the result as on the book, it needs to be 4 / 5 instead of 2 / 5, and the text in the book said "spans back three lines" -- shouldn't it be span back 4 or 2 lines? If we can't count implicit grid, then really it should be 2 / 5, but if we can count implicit grid, then it should be 4 / 5. So was there a spec change? And the "three lines" probably is a typo? So if we need to span 4, then that probably means we count starting on either implicit or explicit grid line?

The code is a bit long but we can just look at box04:

html {
  background: #DDD;
}

body {
  padding: 2em;
  margin: 0;
  box-sizing: border-box;
  background: white;
}

ul.grid {
  padding: 0;
  margin: 0;
}

.grid.boxed {
  border: 1px solid black;
}

.grid.boxed.lines {
  padding: 1px 0 0 1px;
}

.grid.small *[class^="box"] {
  font-size: 1em;
  font-weight: normal;
  padding: 0.25em;
  border-width: 0.167em;
}

*[class^="box"] {
  border: 0.33em solid;
  font: bold 2em Arvo, sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
}

*[class^="box"][class*="01"] {
  color: rgb(255, 0, 0);
  background: rgba(255, 0, 0, 0.1);
}

*[class^="box"][class*="02"] {
  color: rgb(255, 128, 0);
  background: rgba(255, 128, 0, 0.15);
}

*[class^="box"][class*="03"] {
  color: rgb(216, 168, 0);
  background: rgba(216, 168, 0, 0.2);
}

*[class^="box"][class*="04"] {
  color: rgb(0, 128, 0);
  background: rgba(0, 128, 0, 0.1);
}

*[class^="box"][class*="05"] {
  color: rgb(0, 0, 255);
  background: rgba(0, 0, 255, 0.1);
}

*[class^="box"][class*="06"] {
  color: rgb(128, 0, 128);
  background: rgba(128, 0, 128, 0.1);
}

span[class*="gridline"] {
  border: 1px dashed;
  margin: -1px 0 0 -1px;
}


/* for print preview/production
body:hover {filter: saturate(0%);}
 */

#grid {
  grid-auto-rows: 2em;
  grid-auto-columns: 5em;
  width: 35em;
}

#grid {
  display: grid;
  grid-template-rows: 2em 2em;
  grid-template-columns: repeat(6, 4em);
}

.box01 {
  grid-column: 1;
  grid-row: 1 / 4;
}

.box02 {
  grid-column: 2;
  grid-row: 3 / span 2;
}

.box03 {
  grid-column: 3;
  grid-row: span 2 / 3;
}

.box04 {
  grid-column: 4;
  grid-row: span 4 / 5;
}

.box05 {
  grid-column: 5;
  grid-row: span 6 / 5;
}

.box06 {
  grid-column: 6;
  grid-row: -1 / span 3;
}

.box07 {
  grid-column: 7;
  grid-row: span 3 / -1;
}

span[class*="box"] {
  z-index: 1;
}

span.explicit {
  background: #DDD;
  grid-area: 1 / 1 / 3 / 7;
}
<div class="grid gridlines" id="grid">
  <span class="box01">1</span>
  <span class="box02">2</span>
  <span class="box03">3</span>
  <span class="box04">4</span>
  <span class="box05">5</span>
  <span class="box06">6</span>
  <span class="box07">7</span>
  <span class="explicit"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
  <span class="gridlines"></span>
</div>
nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • If you can find a way to make the question more clear, so the problem is easier to understand, that would make this entire post more useful. – Michael Benjamin Jul 25 '20 at 01:49

1 Answers1

2

Can "span counting" start within implicit grid?

No, we start considering the explicit grid and never the implicit grid. Focus on the word start which is the most important because the explicit grid is always the reference and the implicit grid is only the result of extra column/row created in order to contain everything.

As I explained here we cannot consider the implicit grid because we will easily run into undefined behaviors.

Starting considering the explicit grid doesn't necessarily mean that we will be inside the explicit grid. Read until the end to understand this part.


From the specification:

Numeric indexes in the grid-placement properties count from the edges of the explicit grid. Positive indexes count from the start side (starting from 1 for the start-most explicit line), while negative indexes count from the end side (starting from -1 for the end-most explicit line).

And

When grid items are positioned outside of these bounds, the grid container generates implicit grid tracks by adding implicit grid lines to the grid... ref


Let's have some examples to better understand.

Here is a grid with 3 explicit rows (4 lines) and no implicit row created:

.box {
  display:grid;
  grid-gap:5px;
  grid-template-rows:repeat(3,50px);
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:200px; /* This wil never be used */
  border:1px solid;
}
.a {
  grid-row:span 2/3;
  background:red;
}
.b {
  grid-row:span 2/4;
  background:red;
}
.c {
  grid-row:1/4;
  background:red;
}
<div class="box">
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
</div> 

The .a ends at line 3 and span back 2 rows. Same for .b but ending at line 4. For .c we start from 1 to 4.

Let's create an implicit grid by making the .c until 5

.box {
  display:grid;
  grid-gap:5px;
  grid-template-rows:repeat(3,50px);
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:200px; /* This is used for the implicit row */
  border:1px solid;
}
.a {
  grid-row:span 2/3;
  background:red;
}
.b {
  grid-row:span 2/4;
  background:red;
}
.c {
  grid-row:1/5;
  background:red;
}
<div class="box">
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
</div>

Note how the .a and .b didn't move which is trivial in this case because we added a line at the bottom so will not see any trick around the explicit grid.

Now let's add an implicit grid at the beginning:

.box {
  display:grid;
  grid-gap:5px;
  grid-template-rows:repeat(3,50px);
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:200px; /* This is used for the implicit row */
  border:1px solid;
}
.a {
  grid-row:span 2/3;
  background:red;
}
.b {
  grid-row:span 2/4;
  background:red;
}
.c {
  grid-row:span 4/4;
  background:red;
}
<div class="box">
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
</div>

Now it's intresting because we can see that .a and .b are no more starting from 3 and 4 considering the implicit grid but they do inside the explicit one!

For .c we start at the line 4 but we need 4 rows and our grid contain only 3 so we generate implicit rows and we continue the count there.

Basically, we have the follwing steps:

  1. We have the explicit grid
  2. We place items inside the explicit grid (we start the count). Until now there is no implicit grid
  3. we start counting and if we reach the edges and there is no more rows we add new ones. The implicit grid is created.

Another example:

.box {
  display:grid;
  grid-gap:5px;
  grid-template-rows:repeat(3,50px);
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:10px; /* This is used for the implicit row */
  border:1px solid;
}
.a {
  grid-row: 2/span 6;
  background:red;
}
.b {
  grid-row:span 2/4;
  background:red;
}
.c {
  grid-row:span 4/4;
  background:red;
}
<div class="box">
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
</div>

If you inspect the code you can easily visualize the explicit grid (50px height for rows) and the implicit ones (20px height for rows). We start the count considering the explicit grid and we may end in the implicit one.

enter image description here

In the above, we always considered the starting (or ending) to be a number that we can easily identify inside the explicit grid and only the span is larger. Let's now consider the case where the starting (or ending) is also a bigger number than the lines defined in the explicit grid.

.box {
  display:grid;
  grid-gap:5px;
  grid-template-rows:repeat(3,50px);
  grid-template-columns:repeat(3,1fr);
  grid-auto-rows:10px; /* This is used for the implicit row */
  border:1px solid;
}
.a {
  grid-row: 1/span 2;
  background:red;
}
.b {
  grid-row:span 10/8;
  background:red;
}
.c {
  grid-row:span 2/4;
  background:red;
}
<div class="box">
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
</div>

In this case, we defined the .b to end at 8 and span back 10 but there is no line number 8 in the explicit grid. We will then create extra implicit lines in order to have the line 8 and we will count from there and go back 10 rows.

So we started the count from the implicit grid!?

Yes and no. We used the explicit grid to count the lines in order to identify the line 8 (so our reference is always the explicit grid) then when we reach the edge we added more lines to reach 8 then from that point we went back and we created more implicit lines at the beginning.

If we consider the final result of the implicit grid, we cannot say that we started the count from the implicit grid (you can clearly see that it's not the line number 8 in the implicit grid but the last one, the line number 11) but if we consider the fact that the line 8 was created inside the implicit grid then we can say that our starting point is an implicit grid line.

Our reference is always the explicit grid in order to identify the starting/ending line but we may end having our line as an implicit grid line and not an explicit grid line.

box4 is where things really get interesting. It ends on the fifth row line, which is to say the second implicit grid line. It spans back three lines—and yet, it still starts on the same grid line as box3. This happens because spans have to start counting within the explicit grid. Once they start, they can continue on into the implicit grid (as happened with box2), but they cannot start counting within the implicit grid.


the book said "spans back three lines" -- shouldn't it be span back 4 or 2 lines?

Here it's a matter of language. From the specification:

grid span

How many grid tracks the grid item occupies in each axis

Then

Grid track is a generic term for a grid column or grid row—in other words, it is the space between two adjacent grid lines.

So span 4 means 4 rows or 4 columns which is clear but if we try to use this with lines it can be ambiguous because we will have 5 lines involved and our element will cross only 3 of them and we have 2 at the edges. Maybe the book is refering to the 3 middle lines and omitting the ones at the edges when saying "spans back three lines". In other words, the element is overlapping (spanning back) only 3 lines.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/206732/discussion-on-answer-by-temani-afif-in-css-grid-layout-do-we-count-the-span-eve). – Samuel Liew Jan 27 '20 at 15:47
  • You asked me earlier this year to review your answer and provide some feedback. I finally found some time to carefully review the entire post (including the chat). Sorry for the delay. – Michael Benjamin Jul 25 '20 at 01:50
  • Everything about the question is vague and unclear in my opinion. I'm not saying it's a bad question (I can't really tell). At a minimum, the material is esoteric and difficult to understand. After reading the Q & A & chat section multiple times, I still don't fully understand the problem. – Michael Benjamin Jul 25 '20 at 01:51
  • Are we solving for any practical application of grid properties here? Or was the question just the result of a mistake or confusion in the OP's reference material? The latter option seems very possible to me, based on my reading of the Q. We could be on a wild goose chase. – Michael Benjamin Jul 25 '20 at 02:09
  • That said, I think your explanation is as good as it can get. I have nothing to add. – Michael Benjamin Jul 25 '20 at 02:09
  • 1
    @MichaelBenjamin thanks for reviewing. The main issue here is trying to understand if we can start the count from the implicit grid or not. I would say it's a matter of interpretation because (as I explained) the initial line/column can be inside the implicit grid (our start) but we found it considering the explicit grid. The OP is then convinced that, indeed, we can start in the implicit grid which is not totally wrong BUT we always start our counting/finding from the explicit grid to find the starting column (that may end in the implicit grid). – Temani Afif Jul 25 '20 at 08:55
  • 1
    @MichaelBenjamin TL;DR I am trying to convince him that we **always** start counting from the explicit grid and the explicit grid is always our reference so it's clear that we **never** start counting inside the implicit grid BUT the result may end or start inside the implicit grid due to some logical out of range calculation. – Temani Afif Jul 25 '20 at 08:57