✨ Create high-converting landing pages at scaleExplore the AI Landing Page Builder
Tech stack
·6 min read

CSS Subgrid Guide: Syntax, Examples & Best Practices

CSS Grid is the most powerful layout tool currently available in CSS. It allows us to easily create, manipulate, and populate two-dimensional layouts with just a few lines of CSS.

And, in the last few years, that power and flexibility have been expanded even further by the wide adoption of the subgrid value in CSS Grid.

In this post, we’re going to explore subgrid further, examining the problems it solves and how it alters the grids we interact with, as well as look at some examples of it in use.

Before we begin, you should be comfortable with CSS Grid and using it independently. If you want a refresher on it, check out our blog post comparing it to Flexbox.

Subgrid syntax

Before we begin talking about subgrid, what it can do, as well as the problems it solves for us, let’s take a quick look at the syntax for using it.

To start with, when using subgrid, you need a parent grid container, and then any child element inside that grid container can become a subgrid.

For example, looking at the below HTML, we could make the div with a class of child into a subgrid.

<div class="parent">
  <div class="child" />
</div>

If we wanted to do that, we could use the following CSS.

.parent {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(3, 1fr);
}

.child {
  display: grid;
  grid-template-rows: subgrid;
}

In this example, we’ve defined a parent grid with three columns and three rows. Then we’ve configured our child element to create a subgrid using the parent’s rows by providing the value subgrid to the property grid-template-rows. This means that our child grid will use the same grid tracks we defined for the rows on our parent grid, but have its own grid tracks for its columns.

However, you’re not limited to this configuration with subgrid. You can create a column subgrid by providing subgrid as the value of the property grid-template-columns. Or, if you want to, you can create a subgrid for both the columns and rows by providing subgrid to both of the properties we’ve mentioned above.

Nesting grids before subgrid

Subgrid itself, as the name suggests, is concerned with how nested grids interact with each other and any parent grids they’re contained within.

On the surface, nesting grids doesn’t sound too complicated, but there are some nuances to be considered when nesting grids without using subgrid. To highlight this, let’s look at the example below.

Image of nesting grids before subgrids

Here is the example on CodePen:

In this example, we have a parent grid defining the columns for the three blog post cards. Each blog post item also has a grid that defines the rows for the image, title, and description being shown.

The issue, as you can probably see, is that none of them are aligned. This is because each child grid isn’t aware of the others; it’s just concerned with itself.

But, what if you wanted to display them all equally, so the titles and descriptions all aligned with each other? Well, subgrid makes this a piece of cake.

First time here? Discover what Prismic can do!

👋 Meet Prismic, your solution for creating performant websites! Developers, build with your preferred tech stack and deliver a visual page builder to marketers so they can quickly create on-brand pages independently!

How subgrid solves this issue

With subgrid, we can define the row tracks on the parent grid and then provide grid-template-rows: subgrid; to have the child grid use the same row tracks as the parent defines.

This is then done across all of the child grids and allows them to all have uniform rows, ensuring that each image, title, and description is kept perfectly in line regardless of the size of the content in each nested grid.

An image of CSS Grid with Subgrid

Here is the example on CodePen:

Nesting subgrids

Nesting grids with subgrids doesn’t need to stop at one layer deep either. There isn’t actually a limit for how many subgrids you can use inside one another. In the example below, we have three subgrids nested inside each other.

In this situation, when you have nested subgrids, each subgrid infers its size and spacing from its parent in the tree. What this means in practice is that when we control how much space a grid item consumes via grid-column and grid-row, we need to mention the track labels using the direct parent, not the original grid container.

So, for our example, we have an original grid container that has four columns starting at line 1 and ending at 5. It then has three rows starting at line 1 and ending at 4. The first nested subgrid, “Grid 2” then specifies the following CSS for its position in the parent grid.

grid-column: 2 / 5;
grid-row: 2 / 4;

This works because the parent grid, as mentioned, finishes at line 5 for columns and line 4 for rows. This is pretty standard for grids and placing items inside them, but where it gets interesting is nesting another subgrid inside the last one.

In this case, we need to look at how “Grid 2” defines its own grid lines. Because “Grid 2” has one less column vs its parent grid (3 vs 4), it also means it has one less grid line, and they’re slightly out of sync due to how “Grid 2” is placed within the parent.

This means “Grid 2” starts at line 1 and finishes at 4, and the parent grid line 2 is in the same position as “Grid 2”’s line 1. So, when we go to place our next nested grid, “Grid 3” we need to keep this in mind and use “Grid 2”’s line numbers.

When we place “Grid 3”, we use the following CSS. Which means we’ll start at line 3 and finish at line 4 of “Grid 2” for the columns and start at line 1 and finish at line 2 for the rows.

grid-column: 3 / 4;
grid-row: 1 / 2;

Subgrid and line names

Now that we understand how to place items in nested subgrids by using the direct parent’s grid line numbers, I’m going to throw a little bit of a curveball at you.

You can use any parent grid line names to place an item inside a deeper nested subgrid.

In the example above, we have the same three-tier nested grid setup from the last section, but this time the top-level parent grid specifies line names using the CSS below.

grid-template-columns: [wrapper-start] 1fr [page-start] 1fr [page-end] 1fr [wrapper-end];
grid-template-rows: [wrapper-start] 1fr [page-start] 1fr [page-end] 1fr [wrapper-end];

We then use these line names inside the two nested grids, “Grid 2” and “Grid 3” to control where they are located inside their direct parent.

For “Grid 2” this is pretty run-of-the-mill stuff. We place it using the below CSS to refer to the line names we specified above for the parent grid “Grid 1”.

grid-column: page-start / wrapper-end;
grid-row: page-start / wrapper-end;

But, where it gets interesting is that we can define our own names inside “Grid 2” for its columns like so.

grid-template-columns: subgrid [subgrid-start] [subgrid-middle] [subgrid-end];

These new names will be inaccessible to the parent “Grid 1”, but when we’re placing “Grid 3”, we can use them along with the original names specified at the top-level grid “Grid 1”. We can even mix and match them.

grid-column: page-end / subgrid-end;
grid-row: page-start / page-end;

In this case, for the columns, we use page-end from the top level “Grid 1” and then subgrid-end from the direct parent “Grid 2”. Then both of the row line names come from “Grid 1” as well.

Gap inheritance

While we’re talking about subgrids inheriting properties and values from their parent grids, let’s talk about gap inheritance.

When you create a subgrid, it will, by default, inherit the gap property values from its parent grid. However, this can be overridden, and you can specify a gap value specific to the subgrid, which will then be inherited by any subgrids that are a child of it.

You can see this in practice by looking at the example CodePen below.

Helpful tip for working with grid and subgrid

Working with CSS grid can be confusing, and subgrid can exaggerate this. So, to help with this, there is one helpful tip I have for you. Use your browser’s dev tools to your advantage.

Modern browsers like Chrome and Firefox have built-in tools for helping developers build with grid and subgrid. These tools allow you to inspect grids on the page, see their tracks and lines overlayed on the page content, as well as see the gap between each grid track.

These features combined allow you to get a better understanding of the grid/subgrid you’re building and how it interacts with the content you’re placing inside it and any amendments you may need to make to the grid.

Recap

Throughout this post, we’ve looked at CSS grid and how subgrid works within it to help us build more flexible and powerful layouts in our projects.

We’ve looked at how to create subgrids and control how content is placed inside them across both the parent grid and nested subgrids within. We also looked at some examples of using subgrid in practice in some example situations to see exactly how subgrid can help us.

If you’re interested in learning more about subgrid, check out the current MDN documentation for it here. You can also see the current support for subgrid by checking out the caniuse page here. Finally, if you’re interested in reading more about CSS grid overall, check out our post comparing it to Flexbox here and how grid can be implemented using TailwindCSS here.

Thanks for reading.

Article written by

Coner Murphy

Fullstack web developer, freelancer, content creator, and indie hacker. Building SaaS products to profitability and creating content about tech & SaaS.

More posts
Coner Murphy profile picture.

Join the discussion

Hit your website goals

Websites success stories from the Prismic Community

How Arcadia is Telling a Consistent Brand Story

Read Case Study

How Evri Cut their Time to Ship

Read Case Study

How Pallyy Grew Daily Visitors from 500 to 10,000

Read Case Study

From Powder to Pixels - Perfectly Planned Ski Vacations, Now Perfectly Digital

Read Case Study