CSS Grid Layout – creating complex grids

With the Blink and Webkit implementation moving on at great pace, a number of updates to the specification, and Mozilla announcing an Intent to implement CSS Grid Layout, 2015 really is shaping up to be a good year for Grid. As part of my exploration I’ve been looking for good examples of grids in use to rebuild, to see how Grid works for these uses.

In this post I’ve assumed a bit of Grid knowledge, so if you need an introduction to the CSS Grid Layout Module then take a look at my Grid by Example site.

I’ve been looking at the Susy Grid recently. Susy claims to be a semantic grid system – as in it doesn’t require that you pepper your markup with classes to control the grid. It’s also “grids on demand”, you create the grids you need in your Sass, and Susy creates the CSS for you. Crucially, Susy deals with the often complex mathematics needed to use grid structures with the layout tools we currently have.

My experiments have left me impressed. The current state of CSS layout means that unless you like to spend a lot of time doing calculations something like Susy is really useful. The output CSS is pretty much what I’d come up with myself, which to me is the acid test for tool use, “does it write what I would but faster?”

Back to CSS Grid Layout. It should remove the need for preprocessor based solutions for the maths at least, as with Grid Layout you don’t need to do complex calculations to position elements. Let’s test that out.

I found this post about Susy. The author takes a relatively complex grid and uses Susy to lay it out. It’s a good example of what Susy can do, so can we achieve this with the Grid Layout Module?

The HTML and styling CSS

I took the HTML for the Grid and the styling for the coloured boxes directly from the article, and just added a bit of text styling for the headings. Without any layout applied it looks like this.

Layout with no Grid

We need to set up our 10 column grid using the div with a class of container.

.container {
  width: 90%;
  margin: 0 auto 0 auto;
  display: grid;
  grid-template-columns:  (col ) 4.25fr repeat(9, (gutter) 1fr (col) 4.25fr ) (gutter);
  grid-template-rows: auto repeat(5, 100px);
}

The value of the grid-template-columns property gives me a line with a name of col, with a grid track of 4.25 fraction units. I then repeat a pattern of a line named gutter, then a 1 fraction unit gutter track and the col line and track nine times. I finish off with a line named gutter.

For the rows I have created a single row with a height of auto to place the header in and then a repeating pattern of five 100 pixels rows.

I don’t need to give the rows a fixed height but it makes the example a little clearer.

I’m using named lines and line-based placement for this complex grid, and it really is just a case of popping each block onto the grid, pretty straightforward.

Nested Grids

In the example we have some nested elements. The div with the class ag2 contains ag4 to ag7. The div with the class ag7 is then a wrapper for ag8 to 10.

We need to make each of these nested grids a grid too. Once they become a grid we have to declare columns and rows and position their children on the new Grid, not the Grid declared on the outer.

So on ag2 I first position ag2 itself, then make it a grid and declare the columns and rows.

.ag2 {
  grid-column: col 3 / span gutter 6;
  grid-row: 2 / span 5;
  display: grid;
  grid-template-columns: (col) 4.25fr repeat(5, (gutter) 1fr (col) 4.25fr ) (gutter);
  grid-template-rows: repeat(5, 100px);
}

I’m using the same fraction units here as for the outer but as these are fraction units they are not the same width as the outer as they take their percentage width from their grid container.

This could be solved by the proposed subgrid keyword. This is currently marked as “at risk” in the editor’s draft of the Level 1 spec and may get punted to Level 2 due to the complexity of implementation. It’s therefore not part of the Blink implementation. If we had subgrid we would be able to declare ag2 as a subgrid.

.ag2 {
  grid-column: col 3 / span gutter 6;
  grid-row: 2 / span 5;
  display: grid;
  grid: subgrid;
}

It would then inherit the grid from the parent, ensuring that elements maintained that strict grid.

You can see the problem clearly once we have positioned the nested ag7 in the completed example below. The much smaller container meaning our gutter looks far too wide in proportion.

There are ways round this, using absolute units for example for gutters, however I’d definitely like to see the implementation of subgrid, it would make using grids far more natural and simple for authors. Although like many things making something simple takes a lot of work!

The completed example

Other than the subgrid issue, creating this grid just works. We end up with a layout that looks like this.

Completed Layout

You can see the worked example here, using Chrome with the experimental web platform features flag enabled.

There is no complex maths to do, working out your position on the grid can be a little tricky but that is something good tooling could really help with. I would have thought it possible to create a browser plugin, or just some JavaScript to use in development that could overlay a grid with line numbering based on what was declared in the column and rows definition. The important thing is that this is all native CSS, with no reliance on preprocessors, and with no need for clearing, or the layout hacks we currently have to use.

It’s worth noting that I fixed the height of the rows to match the original example. With Grid it’s trivial to have full height columns. For example if I want those sidebars to be full height, I just set them to span 5 rows of the grid.

.ag1 {
  grid-column: col / span gutter 2;
  grid-row: 2 / span 5;
}

This is not so easy to do with existing layout methods.

Layout with full height columns

If you want to know more and see my other examples check out Grid by Example. I also spoke on this subject for CSS Conf EU last year, and that talk introduces the basic Grid concepts.

I’ll be presenting on Grid Layout at various conferences this year with an updated talk – coming up is Fluent, and An Event Apart Boston. I’m also leading a workshop on CSS Layout Modules for Future Insights Live in Las Vegas.

Leave a Reply