Simplify Your Layout (And Your Life) With CSS Grid

How emerging web technologies enable new ways of approaching design and layout

Vlad Sabev

--

Over my career as a web developer, I’ve written my fair share of CSS layouts — from common websites through business tools to messenger applications. And most of the time, it has been an endless pit of despair, a teeth-falling-out nightmare, the bane of my existence!

This is how I feel about CSS in general

Okay, maybe I’m being a bit dramatic, but have you ever found yourself stuck for hours trying to get an element to center vertically, expand to fill its container, or fit properly on smaller devices? If you have, then you probably share my sentiment — doing layout in CSS is really hard.

Or, at least, it used to be — until I learned about CSS Grid. But to show you the new way, let’s first go through what I used to do before…

Behold the villain

I’ve had to write this specific layout multiple times — a header, a sidebar, and some content. For the purpose of this post, let’s call it HSC:

Absolute Positioning

When I first started with UI development, my weapon of choice for this was absolute positioning — it’s straightforward math where you work with coordinates:

#header {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 75px;
}
#sidebar {
position: absolute;
top: 75px;
bottom: 0;
left: 0;
width: 350px;
}
#content {
position: absolute;
top: 75px;
right: 0;
bottom: 0;
left: 350px;
}

Logically, the sidebar and content start where the header ends — at 75px from the top. The sidebar takes up 350px on the left side, and the content starts from that point all the way to the right.

It’s not too bad — until you decide to adjust the height of the header or the width of the sidebar, and realize you also have to change it in a bunch of other places. Of course, this issue is easily solved by using CSS variables or a scripting language like SASS:

$header-height: 75px;
$sidebar-width: 350px;

Here’s the final result where I’ve replaced all hardcoded values with variables:

But even with the help of variables, any time you want to make changes, you have to start calculating coordinates again. Consider how you would add a new element to that layout —you’d have to consider the top, right, bottom, and left positioning of all other elements, and adjust accordingly. Heaven forbid you wanted to add a 10px gap between all the different areas, or conditionally move or completely remove certain elements on smaller resolutions.

What about Flexbox?

When all major browsers finally added official support for the CSS Flexbox spec, many companies adopted it, and some even shipped it to production. I, for one, welcomed our new Flexbox overlords, and was quick to proclaim the end of all my CSS woes.

Yay for Flexbox!

It was great for a while, and I would use it for anything — from building the perfect vertically-centered menu to positioning avatars, chat messages, and buttons inside a card.

However, as far as the hallowed HSC layout was concerned, it actually felt more uncomfortable doing it the new (supposedly better) way:

<div class="flex-column">
<div id="header"></div>
<div id="flex-row">
<div id="sidebar"></div>
<div id="content"></div>
</div>
</div>

No, no, no, I’m not even getting into this — 2 wrapper elements just to use Flexbox?

I think I’ll stick with absolute positioning, thank you very much

Use the Grid, Luke

I had heard of CSS Grid before, but it wasn’t until I stumbled upon this talk that I really started paying attention:

There’s also a Smashing Magazine article written by the speaker

Basically, CSS Grid allows you to split a container into rows and columns and define how its children should fit inside. Instead of thinking about the coordinates of individual elements, you can now think of the behavior of their parent.

It’s not table all over again either, because you don’t need special tags like tr and td to create rows or columns — the DOM can remain flat if you want it to.

Here’s how you could rewrite the HSC layout with CSS Grid:

body {
display: grid;
grid-template-rows: 75px auto;
grid-template-columns: 350px auto;
}
#header {
grid-row: 1;
grid-column: 1/3;
}
#sidebar {
grid-row: 2;
grid-column: 1;
}
#content {
grid-row: 2;
grid-column: 2;
}

After defining the rows and the columns of the grid, you place each element in its appropriate cell:

  • Header — row 1, columns 1 to 3 (excluding 3, meaning columns 1 & 2; alternatively, you can write span 2)
  • Sidebar — row 2, column 1
  • Content — row 2, column 2

And, if your browser supports it, it should look exactly the same way:

If you open the developer tools, your friendly neighborhood browser might even show helpful lines to indicate how exactly the grid is distributed. I’ve gone one step further and annotated the row & column of every cell in yellow for you:

Gee, thanks, Mr. Browser!

This way, you stop thinking about coordinates and start thinking about your application in terms of different areas. And if you do need to adjust the size of the rows and columns, you can do so in a single place — the container element:

body {
display: grid;
grid-template-rows: 100px auto;
grid-template-columns: 400px auto;
}

Grid areas

There’s something even cooler that CSS Grid allows you to do — instead of placing your elements at specific rows and columns, you can assign a named area to each one:

body {
display: grid;
grid-template-rows: 75px auto;
grid-template-columns: 350px auto;
grid-template-areas: 'header header '
'sidebar content';
}
#header {
grid-area: header;
}
#sidebar {
grid-area: sidebar;
}
#content {
grid-area: content;
}

This extremely visual, almost ASCII-art-like way of describing your layout, makes it very intuitive to move stuff around.

How about making the header only span 1 column, with the content spanning both rows, like this:

body {
grid-template-areas: 'header content'
'sidebar content';
}

Check.

What if you wanted to make the sidebar take up both rows in the right column:

body {
grid-template-areas: 'header sidebar'
'content sidebar';
}

Check and mate. We only had to switch sidebar and content.

On a scale of 1 to 10, how cool is that?

This is how I feel about CSS Grid

If you’d like to play more with this design, here’s the pen:

Responsive design

Perhaps you’ve noticed that in the collection of pens I showed you in this post, I’ve also implemented a responsive version of the design, better suited for mobile devices:

Here, the sidebar is hidden to the left, giving way to the content. If we need the sidebar, we can expand it by tapping the > button in the top left corner (also commonly known as the hamburger menu, and portrayed as ☰).

You can judge for yourself what the pros and cons of using CSS Grid for responsive design are. In this case, it seems to me that rows and columns work better than grid areas.

Animation

According to the spec, CSS transitions should work on grid-template-rows and grid-template-columns. However, I was unable to get a sweet animation when transitioning the sidebar and content between the wider and narrower responsive designs. Animation worked just fine with the absolute positioning approach.

Browser support

While most modern browsers support the spec well, older versions of the Android browser don’t, and IE has implemented a previous version of the specification that differs significantly.

A great design tip I stumbled upon was that you should start with a linear, mobile-first layout, then incrementally improve it for larger resolutions using CSS Grid. If the browser doesn’t support it, then your website safely falls back to the already great-looking linear design!

Overall, you should consider what your users’ devices are before completely switching to grids. Be smart, don’t just fall for all the hype I’m selling you 😉

Go explore!

There’s a ton more you could do with CSS Grid, like define multiple rows and columns at once using repeat, use grids within grids (gridception!), and even add gaps between cells:

Try using grid-gap for a super-easy image gallery!

I once again encourage you to watch the video I posted before, read the Smashing Magazine article by the speaker, and browse through the treasure trove of examples out there.

So, congratulations — if doing layouts in CSS was really hard before, with display: grid it's now just hard 😐

But wait, what do you think? Is CSS Grid going to solve our most pressing layout troubles? Or become the next proverbial hammer where every problem looks like a nail? Or is it just an overhyped fad that doesn’t really change things all that much? Your move.

--

--