As the Grid auto-placement algorithm lays out items in the container, it uses next available empty cells (source).
In your source code the A element comes before the B element:
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
Therefore, the grid container first places A, then uses the next available space to place B.
By default, the auto-placement algorithm looks linearly through the grid without backtracking; if it has to skip some empty spaces to place a larger item, it will not return to fill those spaces. To change this behavior, specify the dense
keyword in grid-auto-flow
.
http://www.w3.org/TR/css3-grid-layout/#common-uses-auto-placement
grid-auto-flow: dense
One solution to this problem (as you have noted) is to override the default grid-auto-flow: row
with grid-auto-flow: dense
.
With grid-auto-flow: dense
, the Grid auto-placement algorithm will look to back-fill unoccupied cells with items that fit.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
7.7. Automatic Placement: the grid-auto-flow
property
Grid items that aren’t explicitly placed are automatically placed into
an unoccupied space in the grid container by the auto-placement
algorithm.
grid-auto-flow
controls how the auto-placement algorithm works,
specifying exactly how auto-placed items get flowed into the grid.
dense
If specified, the auto-placement algorithm uses a “dense” packing
algorithm, which attempts to fill in holes earlier in the grid if
smaller items come up later. This may cause items to appear
out-of-order, when doing so would fill in holes left by larger items.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
grid-row: 1
Another solution would be to simply define the row for the second item.
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container {
display: grid;
grid-template-columns: 240px 1fr;
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
dense
fills empty spaces from the start of the grid to the end. So if you have two empty spaces preceding your placed grid item, you will fill those left to right. – Charters