A Revised Subgrid Specification

When you use CSS Grid Layout by setting the value of the display property to grid or inline-grid, only direct children of that element become grid items. If you declare a grid for your layout on a containing element, you can’t then position elements nested in markup on that grid.

The Grid Layout specification contains details of the subgrid keyword. Having subgrid would mean that it would be possible to position elements nested further in markup on a main grid, however this has not been implemented by any browser as yet and is marked as ‘at risk’ in the Working Draft, which says:

‘“At-risk” is a W3C Process term-of-art, and does not necessarily imply that the feature is in danger of being dropped or delayed. It means that the WG believes the feature may have difficulty being interoperably implemented in a timely manner, and marking it as such allows the WG to drop the feature if necessary when transitioning to the Proposed Rec stage, without having to publish a new Candidate Rec without the feature first.’

p. It may not imply that the feature will be dropped, but it appears to give a decent get out clause should no browser implement the feature! Several of us who have looked into the Grid specification in some depth, feel strongly that the feature should be implemented. For background reading here is an older post of mine, and this excellent post from Eric Meyer outlining the issues. I was therefore glad to see some thinking around the subject from Igalia who are implementing Grid in Blink and WebKit.

In the past two weeks a revised proposal was posted to the CSS Working Group mailing list. The hope is that a revised, simplified proposal would mean that subgrid will be implemented and that the version of grid layout that ships in browsers will contain some level of functionality, enabling a master grid to be defined on a parent element and then direct children, and also nested elements be positioned against the lines of that grid.

The revised proposal is not the easiest thing to understand, I had to get clarification after reading it, and I’m sure someone will be along to correct me if I have misrepresented any part of it in this post. There is a lot in that email that is most of interest to browser implementors, so I thought I would highlight the issue with the most initial impact on how we build websites – in the hope of encouraging some feedback.

What does the spec currently say about subgrid?

The current Editor’s Draft dated 22 April 2016 describes subgrid in the same way as the Working Draft dated 17 September 2015:

“A grid item can itself be a grid container by giving it display: grid; in this case the layout of its contents will be independent of the layout of the grid it participates in.

In some cases it might be necessary for the contents of multiple grid items to align to each other. A grid container that is itself a grid item can defer the definition of its rows or columns to its parent grid container by using the subgrid keyword in grid-template-rows and/or grid-template-columns, making it a subgrid in that dimension. In this case, the grid items of the subgrid participate in sizing the grid of the parent grid container, allowing the contents of both grids to align.”

What this describes is the fact that right now you can nest grids.

In the below CodePen I have a grid declared on wrapper, inside are a set of div elements which are all direct children of that element and so are laid out on the grid using auto-placement. There are also elements nested inside the div with a class of i. These are not direct children and so are not positioned on the grid, but I can also add display: grid to i and set up some columns using grid-template-columns at which point the child elements will place themselves onto the grid declared on i.

See the Pen Grid with nested Grid by rachelandrew (@rachelandrew) on CodePen.

The nested grid in this example has no relationship to the grid on wrapper. I can’t line up the nested grid items with items that are controlled by the parent.

If instead we used the unimplemented subgrid keyword for grid-template-columns this would mean that columns in the nested grid would be taken from the parent. In the case of our example we would end up with a three column grid on box i, with the same flexible proportions as used on the overall grid. As in this image.

Using subgrid in one dimension mockup image

In both our parent and our subgrid we are making use of the implicit grid. Grid lines can be explicit, these are the lines we create by specifying grid-template-columns and grid-template-rows or implicit, these are lines created when we position things outside of the grid. A common use case being when we want to specify columns but then just allow as many rows to be created as required by our listing of products or images or whatever it is we are laying out.

What does the revised proposal say?

You can read the full proposal on the CSS WG list here. I’m going to point out a couple of things I feel are important for discussion by the wider community.

A subgrid is for both dimensions (rows and columns)

The way we specify that a grid is a subgrid changes in this new proposal. Instead of setting display: grid and then declaring subgrid on the grid-template-columns and grid-template-rows properties, we set display: subgrid and then do not add grid-template-columns and grid-template-rows properties at all. If we did add these properties, once we have declared a subgrid they will have no effect.

What this means is that for a subgridded element’s children to line up to the parent grid, it will have to do so both for the rows and the columns. For our example above we would need to change the outer grid to allow for two row tracks to accommodate the subgrid.

See the Pen Grid with subgrid new proposal by rachelandrew (@rachelandrew) on CodePen.

A subgrid has no implicit grid

The other implication of subgrids having to apply in both dimensions is that a subgrid has no implicit grid, therefore we cannot have an area where we use subgrid to line up columns, and then add as may rows as needed for the content added. We have to know the number of available rows, and only add the correct amount of content to fill them.

Adaptable components

In many cases (and my example above) you can get nested grids to line up fairly easily without using subgrid as long as you are aware of exactly what the parent grid looks like at that point. For example in my initial nested example, change the grid-template-rows value to 1fr 1fr 2fr and the proportions will match that of the outer grid.

Likewise with a subgrid in both dimensions. If you know what content you have for the subgrid, you can create enough tracks in the outer grid to contain these items.

However one of the key use cases I see for subgrid is in enabling creation of components that can adapt to their container. In my example, if the three column two row nested component was nested inside box g spanning two column tracks I would want it to display as two columns and three rows.

mockup image of a component grid

Neither nested grids (I would need to re-specify my column tracks) nor subgrid (I can’t use an implicit grid so only have two rows) would enable this.

Is single dimension subgrid an “edge case”?

The requirement for single dimension subgrid has been described as relatively rare. Perhaps in practice it is. I would certainly rather have some level of subgrid support in Level 1 of the specification than nothing.

I think that subgrid is an important part of this specification. I think that without it the promise of being able to create try grid-based layouts falls short. Worse, I think without it we will see developers and frameworks essentially stripping semantic markup, because a flat structure then becomes easy to lay out on the overall grid where a nested structure is not.

The question then is, if this flattening of markup potential is something we want to avoid, does the revised specification go far enough to prevent it?

2 Comments

Matt April 26, 2016 Reply

Seems more complex than it needs to be, why can’t HTML5 just have elements like and then give them attributes too?

Something like ‘gap’ isn’t required because we already have border styling for that. ‘Box’ seems odd when ‘grid’ is all that is needed. A subgrid would just be …another grid, no need to call it subgrid in the code itself though (am I missing something?)

Kevin Garcia April 27, 2016 Reply

For subgrids —

What if we used display: grid if the grid being re-declared, or display: grind-inherit (or sub-grid), if it is to inherit the grid lines from it’s parent?

Leave a Reply