Subgrid is an additional feature to CSS Grid introduced in Level 2 of the specification which allows nested grids to participate in the sizing of their parent grids.

When CSS Grid was initially released in 2017, designers and developers were very excited about the prospect of a layout system that was designed and optimised for doing two-dimensional layout on the web. CSS Grid allowed us to do many things with an ease that was not possible before.

However, it also came a certain limitations. One of the bigger ones was the fact that nested grids were unable to participate in the sizing of their parent grids. This was a feature which was deemed important from the start, however, due to its complexity, it was deferred to Level 2 of the CSS Grid specification to allow implementors and specification editors more time to work through the various use-cases to ensure more robust implementation.

This entry will cover subgrid capabilities only. For information about CSS Grid, please refer to the entry on Grid.

Establishing a subgrid

The CSS Grid Layout Module Level 2 introduces 2 new values to the grid-template-columns and grid-template-rows properties, which allow us to establish a subgrid within an existing grid container.

grid-template-columns: subgrid <line-name-list>? grid-template-rows: subgrid <line-name-list>?

The keyword subgrid indicates to the browser that the nested grid will use the same sizing as its parent grid for the portion occupied along the relevant axis. Hence the subgrid’s items will placed and sized according to its parent grid’s track sizing. Subgrids can take the track sizing of their parent grid along a single axis (row or column), or along both axes.

When an element has a display value of grid , an independent grid formatting context is established. A subgrid’s contents participate in its parent grid formatting context, and does not establish a new grid formatting context.

The syntax of <line-name-list> is defined as follows:

<line-name-list> = [ <line-names> | <name-repeat> ]+ <line-names> = '[' <custom-ident>* ']' <name-repeat> = repeat( [ <positive-integer> | auto-fill ], <line-names>+)

If you have used the repeat() function when using Grid, one thing to note is that there is a slight difference when using it in the context of a subgrid, as in this case, only line names are repeated.

.subgrid-container { display: grid; /* you must still apply a display: grid to the subgrid */ grid-template-columns: subgrid; grid-template-rows: subgrid; }

The subgrid will not have any implicit grid tracks in the subgridded axis (or axes) because its grid tracks match up to that of the parent grid. Line numbers on the subgrid start from 1, and do not follow that of the parent grid.

1 2 9 3 4 5 6 7 8 10 1 2 3 4 5 6 7 8

However, if there are any line names on the parent grid, they will be inherited by the subgrid, but it is also possible to provide line names local to the subgrid. The parent grid will not be able to use those line names as they only apply to the subgrid.

Say we have the following markup for a page with a sidebar and some content, and within the content, there is an article and an aside:

<body class="grid-container"> <nav class="sidebar"></nav> <main class="content"> <article> … </article> <aside> … </aside> </main> </body>

We can allow the children within the main element to participate in the parent grid with the following CSS, as well as assign local grid line names to the columns of the subgrid as well.

.grid-container { display: grid; grid-template-columns: [gridcol-1] 1fr [gridcol-2] 1fr [gridcol-3] 1fr [gridcol-4] 1fr [gridcol-5]; } .content { /* placement for the subgrid container itself */ grid-column: gridcol-2 / gridcol-5; display: grid; /* number of line names must match number of lines from parent grid */ /* excess names are ignored */ grid-template-columns: subgrid [subcol-1] [subcol-2] [subcol-3] [subcol-4]; } article { grid-column: subcol-1 / subcol-3; } aside { grid-column: subcol-3 / subcol-4; }

The number of line names declared on the subgrid should match the number of lines which the subgrid spans across the parent grid. Any excess names declared will simply be ignored.

[gridcol-1] [gridcol-2] [gridcol-3] [gridcol-4] [gridcol-5] [subcol-2] [subcol-1] [subcol-3] [subcol-4]

Understanding subgrid item sizing behaviour

There are a number of additional things to note with regards to other layout CSS properties. Line numbering and placement rules obey the subgrid’s own writing-mode , which is also the case for a normal nested grid.

As mentioned earlier, a subgrid will not have any implicit grid tracks along the subgridded axis (or axes). In the event a subgrid item is placed outside the explicit grid or spans an area larger than the explicit, the subgrid item will be “clamped” to the explicit grid.

.grid { display: grid; grid-template-columns: repeat(5, minmax(2em, 1fr)); } .subgrid { grid-column: 2 / 4; display: grid; grid-template-columns: subgrid; } .subgrid__item-1 { grid-column: span 3; } .subgrid__item-2 { grid-column: 4; }

In the above code example, the first subgrid item should span 3 grid columns, however, the subgrid only takes up 2 columns, as such, the browser will clamp the size of this item to the 2 columns of the subgrid. Similarly, the second subgrid item has been placed outside the explicit grid, and again, it ends up being placed into the last grid column of the subgrid.

1 2 3 4 5 2 1 3 4 grid-column: 4 grid-column: span 3

Any margins, borders and paddings applied to each edge of the subgrid will manifest themselves as an extra layer of margin to the subgrid items at those edges. This extra “layer” of margin will accumulate if there are additional nested subgrids.

The above diagram shows a subgrid within a subgrid, and both are participating in the outermost grid’s column sizing only. The outermost grid also has a grid gap applied. Item 2 and Item 3 are nested subgrid items, in other words, grandchildren of the outermost grid.

Item 2 is aligned according to the outermost grid’s columns but its size is reduced by the margin, border and padding of its parent grid and grandparent grid. Item 3 does not have this issue because it is not at an edge.

Grid gaps set on the parent grid are inherited by the subgrid. However, it is possible to override this with a grid gap value that is local to the subgrid. This will also impact the sizing of the subgrid items.

In the above diagram, the parent grid has a gap of 1.5em , while the subgrid has a gap of 2em . Even though the subgrid items are still aligned to the parent grid, when compared to a grid item that spans the same column size, the subgrid item is 0.5em smaller.

Understanding subgrid item alignment behaviour

A subgrid will always be stretched in the subgridded dimension. This means any align-self or justify-self properties will be ignored. Any height or width constraints on the subgrid are also ignored.

The subgrid will always be aligned with the section of the parent grid that it spans. Any justify-content or align-content properties on it will be ignored in the subgridded dimension.