The CSS Grid

Decades ago, when boy bands roamed the earth, and prior to the first dot-com bubble, web developers were rare, and the horizon of expectation among visitors to your company’s website was, well, fairly low.

There were (I kid you not) lots and lots of graphics like this, everywhere.

Site Under Construction

HTML had been engineered to make it easy for developers to set up a “web” of links, and allow visitors / readers to do something really very new: Subvert the literate conventions that the printing press (and later, pulp magazines and paperbacks) had taught us. That is, read from top to bottom; expect each new paragraph to build on the previous paragraph; trust that the author is making a coherent argument, and that her argument will procede logically and intelligently.

When everyone started adding text links (“hyperlinks”) into otherwise plain paragraphs, authors and readers both became convinced that a new world was right around the corner. Academics started throwing around phrases like “reader empowerment” and “reader agency.” They imagined that writers would no longer have it as easy as they once had. Now, readers were ready to click on ideas that interested them, and totally subvert the once-revered intellect of the Writer or the Expert. People began seriously talking about an “attention-based economy.”

All of this makes sense. Imagine that you’re Franz Kafka, and you’ve put together a really memorable opening line:

One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.

But imagine Kafka’s own horror at discovering, decades later, that well-meaning fans of his are adding all sorts of links to the digital version of the man’s works: “One morning” takes you to information about daylight savings time in Eastern Europe, “Samsa” links to genealogical research on the family names “Samsa” and “Samson”; “troubled dreams” to articles on lucid dreaming and dream interpretation; and “horrible bug” takes you to an essay on how different translators have depicted Samsa at the end of this first sentence: Vermin? Cockroach? Insect? Monster? And so on.

You spent days on that sentence! And now – how many readers even make it to the end of that first sentence, before they click on a hyperlink and are whisked away to something altogether unrelated. Why bother writing, at that point?

All of that enthusiasm for the “empowerment of the reader” and the “end of authorship” meant that not many people were paying attention to a fairly sticky problem: Nobody wanted to read anything online. At least, not at length. The pages were ugly, the typefaces blocky, the colors were a horrorshow. Text often went all the way to the edge (and since monitors had chunky rounded screens, there was lots of distortion at the edge.)

How to fix it? The earliest efforts including using the HTML Table element as a kind of layout grid, and jamming your text and images inside those cells.

Sometimes, that worked. But it was clunky, and messed up everyone’s screen reader. Plus, using semantic markup (the table element) to store non-tabular data was clearly contrary to the reason they’d invented mark up in the first place.

It took years (years) to convince developers to stop using tables to build their layouts.

For this project, we’re going to use the CSS Grid. Which, if we’re going to be honest about it, is pretty much just an HTML Table with a sexier name.

As always, there are millions of ways to do this. I’m going to show you my preferred approach. I encourage you to experiment with other approaches, too.

Nota Bene that I’m going to build out the HTML and CSS at the same time in this tutorial, since they depend on each other so completely.

The Grid has at least two parts: The container (the “grid” itself); and the cells (all of the boxes that rest inside the grid). Think of it as a game of TicTacToe. There’s the board you draw on a piece of paper; and then there are those nine empty cells that you created by drawing that board.


For our container, I’m going to create a <div>...</div> element right inside my <body>...</body> element. To make use of it, though, I’m going to need to assign it a CSS custom class. Let’s call that class “my-grid-container” (you can call it whatever you will). Here’s what I’ll put into my HTML file:

  <div class="my-grid-container">

Now that I’ve got a container, I’ll need to “activate” the grid in my CSS file. Here’s how that looks:

  display: grid;

Just about any block-level element can contain a grid. In the CSS, I’ve used a custom class (indicated by the dot in front of the selector’s class name) but I could just as easily put it inside, say, an <article>:

article {
  diplay: grid;

The trick, of course, is that once I’ve assigned display: grid to my <article> element, I’m stuck with it like that (and there is typically only one <article> per HTML page). Using the class selector just makes more sense, then, since it is more flexible. So grids are usually a big <div>...</div> element that is wrapped around a whole bunch of little <div>...</div> elements. There are other ways to do it, as always, but that is one approach you’ll see a lot.

Addressing the Grid

That’s all that we need to do to turn the grid on. The grid makes layout – dictating the horizontal and vertical position of stuff on our screen – easier than ever. If I were describing where to put something on the screen to another person, I might say “Put that in the upper left-hand corner,” or maybe “paste that image just below the middle of the screen, closer to the top.” Computers need more precision, obviously, since they are terrible at context. How we describe placement on the grid depends on how dense or open our grid needs to be – that is, how many different places for content do we want along the horizontal and vertical axes?

Let’s assume for a moment that want to create a grid that is 4 blocks wide (across the x-axis), and 2 blocks high (along the y-axis).

A grid.  Image via viget.

Its a little counterintuitive, maybe, but not that bad. It may seem a bit weird that our horizontal “address” goes up to 5, when we have four cells horizontally, or that it goes down to 3, when we only have two cells vertically. But that’s because we want extra flexibility in our virtual paste-up process. We’ll come back to that in a minute. One more thing to understand, first.


Now that we understand this abstract, virtual grid that the computer uses, we need to “instantiate” it: That is, “give it life” on the computer screen. Remember that all we’ve really done so far is tell HTML and CSS that we’re going to use my-grid-container as a grid. But we’ve not yet told it anything specific about that grid.

To do that, there are two properties inside our container that we’re going to set: grid-template-columns and grid-template-rows. To make short work of this task, CSS lets us set (1) the number of columns and (2) the width of each column at the same time. Same deal with rows.

Let’s finish building the grid we started on:

.my-grid-container {
  display: grid;
  grid-template-columns: 25% 25% 25% 25%;
  grid-template-rows: 120px 120px;

The grid-template-columns property, like the grid-template-rows property, is where we tell CSS both the quantity and size of our cells. In the case of columns, I’ve specified that I want 4 columns, each 25% of the total width of my container. And I’ve said that I want two rows, each 120px high. (Remember, specifying width is always easier than specifying height; you’re usually better off dictating the height of a row in pixels or ems, rather than specifying a percentage.)

As is always (ALWAYS) the case, CSS gives us a lot of shortcuts. Here’s the same declaration as before, but expressed differently:

.my-grid-container {
  display: grid;
  grid-template-columns: repeat(4, 25%);
  grid-template-rows: repeat(2, 120px);

There are different reasons for using different shortcuts like this. I’ll go over a few of them later.

So… Now what?

While it can get much more complicated, for the moment… that’s it. We’re done. Now we just paste content into our grid, and let nature take its course.

How? By remembering the idea we discussed last week, the “parent - child” relationship (in our conversation about “inheritance.") Why does that matter? Because in our HTML file, every block-level CHILD of my-grid-container (the PARENT) is now part of the grid, whether they like it or not (“You are part of this family, young lady, whether you like it or not.")

In truth, that makes our life so much easier: It’s like having an intern do the work for us. I don’t have to say “put one thing here, then put another thing here, then put a third thing over here.” I can just say, “now fill in all those boxes, and then go get me a smoothie when you’re finished.”

<div class="my-grid-container">
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>       
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is a grid cell.</div>
    <div>This is the last grid cell.</div>                


Next, we’ll look at more sizing and styling options, and how images work in the grid.

As an exercise, try to build a grid contains your schedule information for the spring semester. You’ll probably need a column for “Day + Time”, one for the “Location”, and one for “Instructor.” One column for your class name, plus three columns for information. Each row would probably be dedicated to a single class.

Need to skip a cell, and leave it blank? CSS will want to fill every slot with a CHILD, so you’ll still need to create a CHILD, even if it is a soul-less, empty shell. Take a look at my example for an idea of how it can work. (Note that grids can be used this way – as tables – but there are better ways to organize information like this. This is merely an exercise.)

As always, though: Build out slowly, methodically. Get one thing to work before moving on to something new. Try to get the same result from different approaches, and make sure you understand why something works before you leave it behind.