Search code examples
csscss-grid

CSS Grid Item Placement


I was trying to learn how to change the order of columns on a very simple grid (grid-template-columns: 1fr 1fr). The answer was quite simple: add the following rule to the second item: grid-row-start: 1; /* grid-row: 1; shortcut also works */.

_________     _________
| A | B | --> | B | A |
---------     ---------

But I can't understand why this works. I'm trying to change the order of columns but I'm using row rules? The second item is already in the first row. What changed after adding that rule?


I tried to make sense of it. I reset the grid and added grid-column-start: 1; to the second item. I ended up with this grid:

_________
| A |   |      #B { grid-column-start: 1; }
---------
| B |   |
---------

After that, I added grid-column-start: 2; to the first item and the result was:

_________
|   | A |      #A { grid-column-start: 2; }
---------      #B { grid-column-start: 1; }
| B |   |
---------

Now, I have to tell the second item to start at the first row: grid-row-start: 1; and I finally got what I wanted.

_________
| B | A |      #A { grid-column-start: 2; }
---------      #B { grid-column-start: 1; grid-row-start: 1; }

But the thing is, I can keep only grid-row-start: 1; and achieve the same result! Why?!


body {
  background: lightgoldenrodyellow;
}

#content {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

h2 {
  text-align: center;
}

.grid {
  display: grid;
  width: 480px;
  height: 240px;
  margin: 4rem auto;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
  font-size: 3rem;
}

.column {
  border: black solid 1px;
}

.colorA {
  background: turquoise;
  text-align: center;
}

.colorB {
  background: aliceblue;
  text-align: center;
}

.column3 {
  /* does nothing */
  display: block;
}

.column4 {
  grid-row-start: 1;
}

.column5 {
  /* does nothing */
  display: block; 
}

.column6 {
  grid-column-start: 1;
}
<div id="content">
  
  <div>
    <h2>Original</h2>
    <div class="grid">
      <div class="column colorA column1">A</div>
      <div class="column colorB column2">B</div>
    </div>
  </div>

  <div>
    <h2>Using grid-row-start</h2>
    <div class="grid">
      <div class="column colorA column3">A</div>
      <div class="column colorB column4">B</div>
    </div>
  </div>

  <div>
    <h2>Using grid-column-start</h2>
    <div class="grid">
      <div class="column colorA column5">A</div>
      <div class="column colorB column6">B</div>
    </div>
  </div>
  
</div>


Solution

  • You need to follow the placement algorithm to understand this:

    The item A will fall into this rule:

    1. Position the remaining grid items.

    The auto-placement cursor defines the current “insertion point” in the grid, specified as a pair of row and column grid lines. Initially the auto-placement cursor is set to the start-most row and column lines in the implicit grid.

    then

    If the item has an automatic grid position in both axes:

    Increment the column position of the auto-placement cursor until either this item’s grid area does not overlap any occupied grid cells, or the cursor’s column position, plus the item’s column span, overflow the number of columns in the implicit grid, as determined earlier in this algorithm.

    So basically, the B is placed at the first column/first row then our cursor will move along the same row trying to find an empty column to place the A and the second column is an empty one.


    What you described is not correct because you assumed that the A will be placed before B which is not the case. We first place items having an explicit position then we place the remaining so if you set #B { grid-row-start: 1; } then B will be placed first.

    B will consider the (2)

    1. Process the items locked to a given row.

    while A will consider (4) like explained previously


    If you specify #B { grid-column-start: 1; } then both will fall under (4) and in such case A will be placed first (it's the first one in the DOM) and will logically get the first row/first column then B will be placed at first column but since the first row is filled by A then it will move to second row


    If both have grid-column-start specified they are still considered inside (4) and we place A then B but here you need to make the difference between "sparse" and "dense". The first one will always increment the cursor (that's why you will have empty spaces) while the second one will always reset the cursor to make sure to fill as many areas as possible.

    Similar questions:

    CSS Grid : How Auto placement algorithm works

    Using CSS GRID Why Im getting this gap?

    How works CSS grid-autoflow?