
CSS Grid Layout Algorithm Step-by-Step Guide
- Transfer

We bring to your attention a translation of an article about a technique that will be useful to developers using CSS in their work.
In this guide, we will cover all the steps in the algorithm for automatically placing elements from the CSS Grid Layout module. Each step is controlled by a property
grid-auto-flow
. In his other articles, “ Introducing the CSS Grid Layout ” and “ Seven Ways You Can Place Elements Using CSS Grid Layout, ” the author reviewed the CSS Grid specification and analyzed how to use Grid to position elements on a web page. However, in these materials, the position of a single element was explicitly specified in the grid. The remaining elements were placed using a certain algorithm.Now we will analyze this algorithm. And the next time you find that the element is not where you need it, you won’t have to scratch your head and wonder how it happened.
Basic principles
Before delving into the details, consider some basic principles.
- Anonymous grid items . If you place the text directly in the mesh container, without wrapping it in any tag, it will turn into an anonymous mesh element. Styles cannot be applied to such elements, but at the same time they inherit style rules from parent containers. Please note that white space inside the mesh container does not create an anonymous element.
- Value of grid spans . Unlike positioning in the grid, the algorithm does not contain separate rules for determining the value of the interval in the grid. If the value is not set, then by default it is 1 (the element occupies only its cell).
- Implicit mesh (grid Implicit) . A grid built on the basis of property values
grid-template-rows
,grid-template-columns
andgrid-template-areas
, is called an explicit grid . If you now determine the position of the element so that it is outside the boundaries of the explicit grid, the browser will generate additional grid lines that will capture this element. These rows, combined with an explicit grid, form an implicit grid. Read more about this in “ Where Things Are at in the CSS Grid Layout Working Draft ”. The auto-placement algorithm can also cause additional columns or rows to appear in the implicit grid.
Now, here's the thing to note. The default value of the property
grid-auto-flow
with which we control the algorithm is row
. The same value will be used in the subsequent explanation of the algorithm. If you explicitly set the property to value column
, then remember to replace all instances of the term row with column in this explanation. For example, “ Placing elements by setting row position, not column ” will turn into “ Placing elements by setting column position, not row ”. Now activate the possibility of using experimental functions in your favorite modern browser , and consider the details of the algorithm when building the layout.
Step # 1: Generate Anonymous Grid Elements
The first thing the algorithm does, when it tries to put all the elements in a grid, it creates anonymous elements. As mentioned above, you cannot apply styles to such elements because there is simply nothing to apply them to.
The following code generates an anonymous mesh element from inter-element text:
1
Anonymous Item
2345
In this example, it should also be noted that the algorithm ignores CSS floats applied to div 2 and div 4.
→ Demo on CodePen
Step # 2: Placing items at clearly specified positions
For this and the next few steps, we will use a grid of nine different elements.
ABCDEFGHI
The first elements to be placed in the grid are those for which positions are explicitly specified . In our case, let it be elements A and B. For now, ignore all the others. Set the positions for A and B:
.a {
grid-area: 1 / 2 / 2 / 3;
}
.b {
grid-area: 2 / 1 / 4 / 3;
}

The algorithm places A and B according to their property values
grid-area
:- Based on the first and second values,
grid-area
sets the position of the upper left corner for both elements. - Based on the third and fourth values,
grid-area
sets the position of the lower right corner for both elements.
→ Demo on CodePen
Step # 3: Layout items by setting row position, not column
Now the algorithm places an element with explicitly specified row positions in the
grid-row-start
and properties grid-row-end
. Set the grid-row value for the elements C and D:
.c {
grid-row-start: 1;
grid-row-end: 3;
}
.d {
grid-row-start: 1;
grid-row-end: 2;
}
To determine the column position, which is not explicitly specified, the algorithm operates according to one of two scenarios in accordance with the packing mode :
- Sparse packing (default).
- Tight placement (dense packing).
Sparse placement at stage # 3
This is the default behavior. The starting row of the column (column-start line) of our element will receive the minimum possible row index (line index). This way we will avoid overlapping space for the current element and cells already occupied by other elements.
The initial row of the column should also come after the element already placed in the same row at this stage . We emphasize: at this stage, and not before this stage.

Consider an example: the element D did not move to the left of A, even though it could fit there without any overlap. The fact is that the algorithm does not place elements with an explicitly specified row position, rather than column- , in front of another element similarly positioned in this row (in our example, C). If the grid-row values are removed from the element C, then D will move to the left of A.
In other words, the element D, which is explicitly given a row position rather than column, can be placed before A, but only if this is not interferes with S. And in this case it interferes, because C, like D, has a row position, not a column, and it is in the same row as D.
→ Demo on CodePen
Tight placement on stage # 3
If you need to fill an empty space in front of A with an element D, you have to assign a
grid-auto-flow
value to the property row dense
..container {
grid-auto-flow: row dense;
}

In this case, the initial row of the column will again receive the minimum possible index, so that there is no overlapping with other elements. But if there is an empty place in the row where our element can fit without overlays, then it will be placed there without taking into account the previous element from the same row and with the same positioning values (in our example - C).
→ Demo on CodePen
Step # 4: Determining the Number of Columns in an Implicit Grid
Next, the algorithm tries to determine the number of columns in the implicit grid. It goes like this:
- The algorithm takes the number of columns in the explicit grid.
- It then goes through all the elements with the given column position and adds the columns to the beginning and end of the explicit grid to cover all the elements.
- Then the algorithm goes through all the elements without a given column position. If the largest span for one of them is greater than the width of the implicit grid, then the algorithm adds columns at the end to cover this interval.
Step # 5: Placing the remaining items
At this point, the algorithm has already placed all the elements whose positions are clearly defined, as well as elements with known row positions. Now he begins to place the remaining elements in the grid.
But before considering this process, we introduce a new term: the auto-placement cursor . This is the current insertion point in the grid, determined by the intersection of a pair of coordinates - a row and a column. Initially, the cursor is placed at the intersection of the initial row and the column of the implicit grid.
Recall that the positioning of elements depends on the packing mode specified by the property
grid-auto-flow
.Sparse placement at stage # 5
By default, the remaining items are placed in sparse mode . Here's how it goes.
If an element has no position on any axis:
- The algorithm increments the column position of the cursor until:
a) until there is overlap between the current element and the previously placed ones,
b) or until the sum “value of the column position of the cursor + value of the column interval of the element” exceeds the number of columns of the implicit grid. - If the algorithm finds a position without overlapping, then it assigns the cursor position to the value
row-start
and thecolumn-start
inserted element. Otherwise, the algorithm incrementsrow-позицию
by 1,column-start
assigns the value of the initial row in the implicit grid, and repeats the previous step.
If an element has a column position:
- The column value of the cursor is assigned to the row value of the
column-start
element. If the value of the new position is less than the previous column position of the cursor, then the row position is increased by 1. - Next, the row position increases by 1 until a value is reached at which the element does not overlap any of the already occupied cells. If necessary, additional rows can be added to the implicit grid. Now the value of the start line of the row of the element is assigned to the row-position of the cursor, and the end row of the row of the element is set in accordance with its interval.
To make it clearer, consider an example.

Placement of elements E and F when no axis positions are specified
When processing an element E that does not have either a column or row position , the cursor sets the values to row 1 and column 1. Element E occupies only one cell; it can fit in the upper left corner without overlapping. That is, the algorithm simply places the element E at the position row 1 / column 1 .
The next element without the specified positions on both axes is F. The value of the column position of the cursor increases to 2. But the position of row 1 / column 2 is already taken by element A. The algorithm has to increase the value of the column position again until it reaches 4. There are no more columns , and then the row-position of the cursor is increased by 1, and the column-position is reset to 1: row 2 / column 1. The algorithm again starts to increase the column-position by 1, until it reaches 4. Place with coordinates2 row / column 4 while it is free and can be consumed element F . The algorithm places it and moves on to the next element.
Placement of elements G and H when a column position is specified
Let's start with G. The value of the column position of the cursor is defined as the property
grid-column-start
of the G element - 3. Since they are smaller than the previous value of column (4), the row position is increased by 1. That is, it becomes row 3 / column 3. Space with such coordinates is currently free, and G can be placed there without overlapping, which the algorithm does. Then the same thing is repeated for the element H. → Demo on CodePen
Tight placement on stage # 5
When a property is
grid-auto-flow
assigned a value row dense
, a different procedure is performed. If the inserted element does not have a specific position, then the current cursor position is determined in accordance with the line at the intersection of the initial row and the implicit grid column, before the position of the element is determined.
The element I is placed to the left of H, because the cursor position is reset to the line located at the intersection of the initial row and the column of the implicit grid , instead of starting from the last placed element. The algorithm searches for a suitable position without overlapping, finds a place to the left of H and places the element there.
→ Demo on CodePen
Conclusion
In this article, we went through all the stages of the automatic placement algorithm from the CSS Grid Layout module. This algorithm is controlled using a property
grid-auto-flow
. Try to calculate the last position of different elements from different layouts yourself in order to better understand the algorithm.