Introduction
Today, we will delve into some of the more complex and distinctive properties of grid layouts: grid-auto-columns
, grid-auto-rows
, and grid-auto-flow
. Mastering these properties will mark you as a true expert in grid layouts. Let’s begin!
grid-auto-columns and grid-auto-rows
Defines the size of any automatically generated grid tracks, also referred to as implicit grid tracks. These tracks are created when grid items exceed the available cells in the explicit grid or when items are placed outside the predefined grid structure.
Let’s return to James’s land planning example:
- Scenario 1: Land division. The plan was to divide the land into 16 areas for shops, and all the construction materials were prepared. However, it turned out that the purchased land could only fit 12 areas. To maximize usage, the extra 4 areas were built outside the purchased land.
- Scenario 2: Land division. The plan was to build a hotel in the north and a church in the south. However, during construction, the hotel was mistakenly built outside the purchased land.
Both scenarios involve constructing additional structures outside the intended land for various reasons. If James wants to specify the size of these areas outside his purchased land, he can use the grid-auto-columns and grid-auto-rows properties. These properties are designed to manage and plan for such situations effectively.
In Grid layout, these non-standard grids are called “implicit grids” (grids that are automatically created to accommodate items placed outside the defined grid), while the grids displayed within the specified container are referred to as “explicit grids” (grids explicitly defined by the developer).
The syntax is as follows:
.container {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
}
Among them, <track-size>
is the size of the divided land. This can be a length value, a percentage, or the fr unit (representing a fraction of the remaining grid space).
Let’s see the style effects of the grid-auto-columns and grid-auto-rows properties in action through an example. The CSS is as follows:
.container {
display: grid;
width: 150px;
grid-template-columns: 60px 60px;
grid-template-rows: 30px 90px;
grid-auto-columns: 60px;
outline: 1px dotted;
}
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
background-color: rgba(11, 51, 15, 0.5);
}
.item-b {
/* The container has only 2 grid cells horizontally, but specifying the 3rd one causes an implicit grid track to be created */
grid-column: 3 / 4;
grid-row: 2 / 3;
background-color: rgba(255,255,0, .5);
}
The width of .item-b is forcibly set to 60px; otherwise, it defaults to auto, barely filling the remaining 30px.
Let me explain in more detail. First, we defined grid-template-columns: 60px 60px;
, specifying that each row contains 2 cells, each 60px wide. However, for .item-b, we mistakenly set grid-column: 3 / 4;
, placing it in the third cell of the row, which doesn’t exist. This creates an implicit grid. To handle such cases, we need to use grid-auto-columns
to define the width of implicit grid tracks; otherwise, its width will be auto, determined by the content.
grid-auto-flow
The grid-auto-flow property controls how grid items without explicitly defined positions are placed. For example, in a 5x2 grid (10 cells), with 5 elements, where 2 items are placed in specific cells and the remaining 3 are left to auto-place, the arrangement of these 3 items will be determined by the grid-auto-flow property.
The syntax is as follows:
.container {
grid-auto-flow: row | column | row dense | column dense
}
Among them:
- row: This is the default value. Grids without a specified position are arranged horizontally first.
- column: Grids without a specified position are arranged vertically first.
- dense: The term “dense” means compact. When enabled, this activates a “dense” packing algorithm. If smaller grid items appear later, the layout tries to fit them into earlier available spaces, making the grid as compact as possible. This only affects the visual order and may cause a discrepancy between the DOM order and the displayed order, which can be problematic for accessibility. Therefore, it is recommended to use this property cautiously.
Let’s see the style effects through an example.
.container {
grid-template: 1fr 1fr 1fr/1fr 2fr 2fr 1fr 2fr;
display: grid;
outline: 1px dotted;
max-width: 420px;
/* change here */
grid-auto-flow: row;
}
.container > div {
outline: 1px dotted;
font-size: 14px;
display: flex;
align-items: center;
justify-content: space-around;
}
.item-a {
grid-column: 1;
grid-row: 2 / 4;
}
.item-b {
grid-row: 1 / 3;
}
.item-c {}
.item-d {}
.item-e {}
<div class="container">
<div class="item-a">
<p class="grid-p">.item-a</p>
</div>
<div class="item-b">
<p class="grid-p">.item-b</p>
</div>
<div class="item-c">
<p class="grid-p">.item-c</p>
</div>
<div class="item-d">
<p class="grid-p">.item-d</p>
</div>
<div class="item-e">
<p class="grid-p">.item-e</p>
</div>
</div>
- row: The items are arranged horizontally, .item-c has enough height to fit into the top-left grid. As a result, the visual order will be: c, b, d, e.
- column: If arranged vertically, .item-c does not have enough width to fit into the top-left grid. Therefore, the visual order (first top-to-bottom, then left-to-right) will be: b, c, d, e.
- dense: If arranged horizontally, and there is available space, the items will “fill in” where there’s room. The visual order behaves the same as with the row property.
- column dense: If arranged vertically, .item-c is placed in the top-left grid, so the visual order (first stacking vertically, then horizontally) is c, b, d, e, with b and d stacked vertically.