Why is CSS Grid a big deal and why should we care?
Well, CSS Grid is the first real layout system for the web. It’s designed for organizing content both into columns and rows and it finally gives developers almost God-like control of the screens before us. That means that we can finally ditch decades of hacks and workarounds for setting elements on a web page – ultimately it means that complex layouts and beautifully typeset pages are now not only possible but easy and maintainable.
With CSS Grid, the web is about to become a much more beautiful place than what we’re accustomed to.
OK, but how does Grid work? There are a lot of complex tutorials out there that go into an awful lot of detail but I think we should start with the very basics. What we’ll be making here is a relatively simple type specimen, with a bunch of characters from an alphabet laid out on a page.
To get started we’ll add our markup:
<div class='wrapper'>
<div class='letter'>
A
</div>
<div class='letter'>
B
</div>
</div>
First up we’ll style those letters to use the right font-size
and color
and then we’ll center those letters in the divs with flexbox properties like align-items
and justify-content
. And yes, that’s right! CSS Grid doesn’t replace flexbox properties as much as it compliments what they already do. We can even use many of these properties in conjunction with CSS Grid. But for now let’s return to the demo:
In the example above we have two simple divs sitting on top of one another because they’re default is display: block
. Next up we’ll set our parent element to use Grid layout:
.wrapper {
display: grid;
}
Which will then lead to this:
See the Pen Type Specimen Grid Demo – 1 by Robin Rendle (@robinrendle) on CodePen.
Now you might see that nothing really happened. And you’d be right! Unlike setting display: inline-block;
or display: inline;
, it’s not entirely clear what happens when we set display to grid
. In fact, to get our grid to actually do something we first need to feed it a certain number of columns or rows. In this example we’ll just align the letters next to each other into two columns:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 1px;
background-color: black;
}
Let’s break these new lines of code down. First we create two columns of our grid with grid-template-columns
. That 1fr
value might seem super weird if you’ve never seen it before but it’s a valid CSS unit that tells each column to be one fraction of our grid. In this instance, that means there will be two columns of equal width.
This will end up looking something like this:
See the Pen Type Specimen Grid Demo – 2 by Robin Rendle (@robinrendle) on CodePen.
Hooray! It works. But see that curious gap between the two columns? That’s the background of the wrapper
peaking through each letter
div and that’s because we’ve set the grid-column-gap
property to 1px. Usually, we’d want to give a larger column-gap
then that, especially if we’re aligning text blocks next to each other. But in this instance, a single pixel is good enough for us.
So what happens if we add two new letters to our markup? How will that change the layout?
<div class='wrapper'>
<div class='letter'>
A
</div>
<div class='letter'>
B
</div>
<div class='letter'>
C
</div>
<div class='letter'>
D
</div>
</div>
Well, technically it won’t change the grid at all – we’ve already told the grid to have two columns so those two letter divs are going to sit in place directly beneath the others and be exactly 1fr
wide:
See the Pen Type Specimen Grid Demo – 3 by Robin Rendle (@robinrendle) on CodePen.
Now here’s the weird thing – why isn’t there a 1px gap between letters A and C as well as between B and D? Well, grid-column-gap
is only for columns and what we’ve effectively done here is create a new row in our grid. We’ll have to use grid-row-gap
to see that change take effect:
.wrapper {
grid-column-gap: 1px;
grid-row-gap: 1px;
/* other styles go here */
/* we could have also used the shorthand `grid-gap` */
}
And here’s what that looks like:
See the Pen Type Specimen Grid Demo – 4 by Robin Rendle (@robinrendle) on CodePen.
We’ve created our very first grid. We’ve made a row and a column and all we’ve really had to do is change the markup. But let’s just explore our columns a little more. What would happen if we add another value to the grid-template-columns
property? Like this:
.wrapper {
grid-template-columns: 1fr 1fr 1fr;
}
Well, we’d create another column of course! And notice how we can clearly see the background of the wrapper element now because there aren’t any children to fill that space:
See the Pen Type Specimen Grid Demo – 5 by Robin Rendle (@robinrendle) on CodePen.
And if we change the value of a fr
in that property then that would effectively create what’s known as an asymmetric grid. Let’s say that we wanted our first column in our grid to take up three times the amount of space as the other two columns:
.wrapper {
grid-template-columns: 3fr 1fr 1fr;
}
That would lead to the columns with A and D to be larger than the other two columns, just as we’d expect:
See the Pen Type Specimen Grid Demo – 6 by Robin Rendle (@robinrendle) on CodePen.
Isn’t that powerful? No longer do we have to worry about negative margins or the perfect % value of a grid column to align things properly. We can make super complex grids without having to do any of the math that we would’ve been forced to do in the past. Now we just need to add a new value to the grid-template-columns
property and voilá, a new grid column appears like magic!
But what about responsive grids, you might ask? Well that’s really just as simple as changing that property within a media query. Let’s say that we want 2 columns as our default grid size then at 500px we want 3 columns and finally, on larger screens, we’ll shift all that content into 4 columns. All we’d need to write is this:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
@media screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 1fr 1fr 1fr;
}
}
@media screen and (min-width: 800px) {
.wrapper {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
Make sure to open up this demo in a new tab and change the size of the viewport to see the responsive magic happen!
So the grid-template-columns
property is a lot more complicated than what I’ve shown here but this is a great starting point. Next up we ought to learn about the real, life-changing property in the CSS Grid spec: grid-template-rows
.
Ok, let’s go into it blind. In the small bit of code below, and with what we’ve learned so far about Grid, let’s figure out what this new property might do:
.wrapper {
display: grid;
grid-template-columns: 3fr 1fr 1fr;
grid-template-rows: 1fr 3fr;
}
Instead of setting the width of columns and their relationship with one another, we’re now going to set the height of rows and their relationship. So if we have two rows like in our previous demo and the last unit is set to 3fr then that means the second row will always be three times the height of the first:
See the Pen Type Specimen Grid Demo – 8 by Robin Rendle (@robinrendle) on CodePen.
This might look pretty simple yet previously we’ve never really been able to do this. We’ve always had to write gross hacks like setting a min-height
on a specific element or changing a class name. But we’ve never been able to create relationships between rows like this before; that’s what makes CSS Grid so powerful.
With this tiny bit of knowledge and a handful of new properties, we can create fabulously complex layouts – asymmetric and responsive grids being just one small part of them. And so far this has only been a glimpse into the monstrous CSS Grid spec, as there’s an awful lot to cover. But I think that Jen Simmons described it best when she wrote about Grid:
We need to explore CSS Grid until we understand what it wants to do, what it can be forced into doing, and what it refuses to do. Many designers may not ever learn to code CSS, but you need to understand CSS well enough to understand our artistic medium.
And sure, all the code above looks very strange at first. But what it means is that we don’t have to use giant CSS frameworks and also a whole bunch of layout hacks are now completely irrelevant. But what really excites me most about Grid is that it compels us to see the space inside a browser in a completely new way.
We’ll have to not only learn a bunch of new properties, but we’ll also have to entirely rethink what we’ve learned in the past. So CSS Grid is not just a spec but a strange philosophy unto itself.
Let’s figure it out together!
Browser Support
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
57 | 52 | 11* | 16 | 10.1 |
Mobile / Tablet
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
123 | 124 | 123 | 10.3 |
More Information
- Jen Simmons and Rachel Andrew have written a lot of amazing tutorials and walkthroughs on the subject
- Grid Inspector Tools in Firefox is super handy
- We have a Complete Guide to Grid which goes into a lot more detail on each property and value
Forgive the basic question, but why is relying on every browser company to build in support (and keep it updated) better than including a css file?
I was on Chrome 56 and none of the demos worked until I updated to 57. In Firefox, same thing. No demos worked until I updated. I also have IE11. They do not work, and I assume they will.
Drat. That should say never will
Did you mean a Javascript file (polyfill)?
Including a CSS file for CSS grid would do absolutely nothing because the older browsers don’t even understand the CSS. If a browser doesn’t understand CSS, it skips over it by design.
The reason you had to update Chrome and Firefox is because only the most recent versions support CSS Grid.
A reasonable question, actually, though I’m not sure I’m the right person to try to answer it, since all my knowledge on modern web design is book knowledge. It mostly comes down to the fact that CSS-grid (the standard) is quite a bit more flexible than the grid systems implemented by non-CSS-grid CSS.
It can easily pull off effects that are difficult or impossible with grid systems without adding a lot of boilerplate, javascript, or assumptions. In particular, it allows the source order to have no bearing on the positioning on the page itself, both vertically and horizontally, as I understand it.
It can also pull off size relationships where the size of the reference “cell” is determined by how the content flows rather than precalculating it. It would be easy to make a demo of each of these using a traditional grid system, but that’s because these demos are all easily precalculated. Imagine trying to set up something like this where the contents of the cells are based off of user input, so you can’t just say “this context will have a height of X*3 so that it is three times as tall as this other context which has a height of X.”
Basically, this article is an introduction to CSS-grid, it doesn’t really go into some of the more advanced things CSS-grid can do. It also doesn’t emphasize the fact that CSS-grid can do this with arbitrary content, resizing the grid as necessary to balance out the grid. And yes, the CSS can provide hints and rules as to how the cells grow and push against each other.
Oh man, until I saw your comment I was very confused. I thought I was misreading but it turns out my Chrome didn’t auto-update like I thought it would. After updating it looks a lot different and makes sense(obviously), but I agree with you, we’re going to have to offer fall-backs in CSS as Developers for a few generations and in that case you may want to forego CSS Grid for the time being, until Generations of Browsers fall off.
In the interim it reminds me of using srcset for pictures. It’s tedious and frustrating and when I have to involve myself with it I sometimes want to punch things, but in the end it does lead to an overall better web experieence.
CSS Grid replaces FlexBox ?
CSS Grid does not replace Flexbox. They can be used together. One of the easiest ways to know which to use:
Use Flexbox for 1-dimensional layouts, such as horizontal or vertical.
Use CSS Grid for 2-dimensional layouts, such as declaring styles for both horizontal and vertical layouts.
So you can use CSS Grid to create a page layout and then use Flexbox on individual elements within that layout.
You can even nest grids if needed.
Not at all, it only implement and share some of the properties. They can work together.
Grid and FlexBox are not mutually exclusive. They’re different tools for different jobs, like a car and a truck or a hand saw and a table saw. You can use them to accomplish similar layouts but they each have their own strengths.
Grid is for global arrangement while flexbox is good for representing items.
For single page application: Grid is for the site layout while flexbox is for internal list items.
Your caniuse data is off. The link points to these stats for css grid support:
Firefox: 52+ (just released)
Chrome: 57+ (just released)
Safari: 10.1 (in beta)
IE: 11+ but an old version of the spec
Edge: current version still on an old version of spec
iOS Safari: not yet
Android: nope
A number of folks responded to this about the browser support data provided.
That data does come from **CanIUse…* and is up-to-date, but I agree it’s a bit confusing because of the way it lists the very first browser to have even partial support for grid.
Raw data is here: https://github.com/Fyrd/caniuse/blob/master/data.json
Rachel Andrews has a plain English browser support page: http://gridbyexample.com/browsers/
in caniuse data “p” is not for “partially supported” but “supported by polyfill” (not used on caniuse.com)
https://github.com/Fyrd/caniuse/issues/665
read more about caniuse syntax here:
https://github.com/Fyrd/caniuse/blob/master/CONTRIBUTING.md
Ah yes! Good call. I altered our backend code to ignore “p” values.
I look forward to it being supported on mobile browsers… quickly!
In trying to get to grips with CSS Grid I have copied your code and played around with the units. Can you advise as to why this doesn’t display properly in Edge, even though I have run it through a PrePros to get the correct prefixes? The only box that shows is the final one. See CodePen in Edge – http://codepen.io/anon/pen/BWdLej
sub-grid possible ?