Towards the end of last year I did some research into the proposed CSS Grid Layout module for my book CSS3 Layout Modules for Five Simple Steps and also an article for 24 Ways. Both of these were heavily based on the Internet Explorer 10 implementation, as that was (and is) the only real implementation of Grid so far.
Since then a new Working Draft has been published which makes some changes to the proposed module. I’m preparing a new talk based on my exploration of the new CSS layout modules and, having researched these changes, I thought it worth writing them up. The latest Working Draft can be found on the W3C website – CSS Grid Layout.
If you spot any errors in this let me know. I am very much a “try it and see how it works” sort of person, so it is a definite challenge to write about things that don’t yet have an implementation. Add a comment if you think any of this looks incorrect and I’ll update the article and credit you of course.
My 24 Ways article is a reasonable example of the Grid Layout properties currently supported by IE10.
If you have not yet come across Grid, it enables us to declare a grid on a parent element and then layout child elements based on a position within the Grid. The exciting part of this for me is that we can lay them out independently of source order. This will be useful in particular for responsive design where elements may make more sense in order order when displayed on a phone touch screen and another on a large monitor.
IE10 supports the following properties with the -ms prefix, some of which have been deprecated and changed in later Working Drafts.
Creating a grid
display: grid (as display: -ms-grid) and display: inline-grid (as display: -ms-inline-grid )
Declares a grid on a parent element. These are new values for the display property. You can nest a grid inside another grid, however the spec also proposes an additional value for the display property of subgrid. This is not implemented in IE10.
If you have a parent element set to display: grid
then the items within it act as grid items and therefore must be positioned on the grid. If one of those items also has display:grid set then the items inside it must be positioned within that child grid.
If you set one of the child items to display: subgrid
the items inside it remain part of the parent grid and can therefore align to elements within the parent. There is an example within the Working Draft of how this should work, however there are also some questions of implementation.
Defining the grid
The grid-columns (as -ms-grid-columns) and grid-rows (as -ms-grid-rows) properties
Once you have declared a grid on an element you must also set up the rows and columns on that grid. These properties, as implemented in IE10, have been deprecated. The new names for the properties are grid-definition-columns
and grid-definition-rows
.
Therefore the code that currently works in IE10 to create a two row, five column grid looks like this.
.wrapper {
display: -ms-grid;
-ms-grid-columns: 200px 20px auto 20px 200px;
-ms-grid-rows: auto 1fr;
}
According to the current Working Draft it would now be:
.wrapper {
display: grid;
grid-definition-columns: 200px 20px auto 20px 200px;
grid-definition-rows: auto 1fr;
}
There are a variety of ways to specify track sizing, and the following are implemented in IE10.
- Standard length units – pixels, ems etc. or a percentage value.
- Keywords – auto, min-content, max-content, minmax(a,b)
- Fraction units – 1fr, 2fr etc.
You can specify these values individually or using a repeating syntax. Therefore the following two declarations are the same.
.wrapper { display: -ms-grid; -ms-grid-columns: 1fr 4.25fr 1fr 4.25fr 1fr 4.25fr 1fr 4.25fr 1fr; -ms-grid-rows: auto 20px auto 20px; }
.wrapper { display: -ms-grid; -ms-grid-columns: 1fr (4.25fr 1fr)[4]; -ms-grid-rows: (auto 20px)[2]; }
However the current Working Draft has this repeat syntax detailed a little differently using repeat notation, so my above example would be as follows using the new properties and the updated repeat syntax. The repeat notation has a number (the number of times to repeat the pattern) a comma and then the pattern to repeat.
.wrapper {
display: grid;
grid-definition-columns: 1fr repeat(4, 4.25fr 1fr);
grid-definition-rows: repeat(2, auto 20px);
}
Placing Grid Items
In the IE10 implementation, items are positioned on the grid using the following properties:
- -ms-grid-row
- -ms-grid-column
- -ms-grid-row-align
- -ms-grid-column-align
- -ms-grid-row-span
- -ms-grid-column-span
In my 24 Ways article and associated CodePen examples you can see these all in action. There are a number of changes in the current Working Draft.
The grid-row and grid-column properties
These are shorthand properties, grid-row combines the new properties grid-before and grid-after, grid-column combines grid-start and grid-end. I’ve had a bit of trouble wrapping my head around these grid-placement properties and the Working Draft even includes the following note.
These are somewhat awkward, but nobody’s been able to come up with a clearer set of four property names. If anyone has suggestions, please, please post them. (Other syntax improvement suggestions are also welcome.)
If I have this wrong, then hopefully someone will come along with a better example!
New grid placement properties
How these seem to work is that they essentially define the borders of the area into which the content sits. So columns have a start and an end line, rows have a before and an after line.
If we take a look at my example from the 24 Ways tutorial we can see how I would need to change it to meet the new Working Draft.
.wrapper { display: -ms-grid; -ms-grid-columns: 200px 20px auto 20px 200px; -ms-grid-rows: auto 1fr; }
.content { -ms-grid-column: 3; -ms-grid-row: 2; -ms-grid-row-span: 1; }
So here I have declared a grid on the .wrapper element. I have used the grid-columns property to create a grid with a 200 pixel-wide column, a 20 pixel gutter, a flexible width auto column that will stretch to fill the available space, another 20 pixel-wide gutter and a final 200 pixel sidebar: a flexible width layout with two fixed width sidebars. Using the grid-rows property I have created two rows.
I then have a div with a class of content that I want to place into the centre column (this is the auto one) and second row (the one specified as 1fr.
In the new draft this would look like this.
.wrapper { display: grid; grid-definition-columns: 200px 20px auto 20px 200px; grid-definition-rows: auto 1fr; }
.content { grid-start: 3; grid-end: 4; grid-before: 2; grid-after: 3; }
The content definition could also be written as:
.content {
grid-column: 3/4;
grid-row: 2/3;
}
The row-span and column-span properties are not required as this syntax specifies a start and end point for each element and therefore span makes less sense. There is a value of span that can be used as a value for the grid placement properties, though this makes more sense when used alongside the ability to name grid lines – perhaps a subject for a future article.
I have updated one of my Examples from the 24 Ways article to the new syntax. Although with the new idea of working to grid lines I think there might be better ways of stating where items should be placed using LESS (or your tool of choice). I’ll think a bit more about that – and if you have any thoughts add them to the comments.
One Comment
As you suggested, I agree the new grid-line syntax is still lacking…
Are you familiar with Greg Badros’s Constraint CSS (CCSS) (https://www.cs.washington.edu/research/constraints/web/ccss-uwtr.pdf)? Although ancient in web years, the underlying concepts and it’s Cassowary Constraint Solver became the foundation for Apple’s new layout system for Cocoa, Auto Layout. Constraint-based layout primitives offer a much more expressive & intuitive layout paradigm. If you’re curious, I created CSS polyfills for CCSS & Cocoa’s Visual Format Language using Alex Russell’s JavaScript port of the Cassowary solver, check it out:
http://gridstylesheets.org/
Also, your book looks great!