We haven’t talked about CSS
much around here, but it has come up so much in my work at Yale that I thought I would write up a really short intro to something that is incredibly useful: CSS
grid. Here goes.
What is CSS
?
CSS
(for “cascading style sheets”) is a standard that lets you change the default display of elements in an HTML
document. You can do a million things with CSS
— change typography, color, spacing, even animate stuff.
But the thing I want to tell you about here is layout.
Here’s the thing we will build:
Hilariously enough, in the olden tymes (like, in 2010) this layout was so freaking hard to make with CSS
that it because known as “the holy grail”. I kid thee not, there is a Wikipedia article about it. I mean, do a million websites not have this layout? Yes, yes they do. Is it somewhat bonkers that it was so hard for so long to make this layout? Yes, yes it was.
I mean, like, even in language documentation a site with this general shape or something similar is going to be useful sooner or later. (Poke around the sites listed in the #web-documentation category and see for yourself.)
Klingon
For instance, let’s design a little faux-text browser for Klingon documentation:
This is a holy-grail-style layout. Amirite?
Well, that settles it.
Let’s see how to do this using CSS
grid.
Let’s make a Holy Grail Layout with CSS
Grid
Our Klingon site’s HTML
might look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Klingon Documentation</title>
<style>
@import url(klingon-text.css); /* don’t worry about this, it’s for formatting the interlinears */
</style>
</head>
<body>
<header>
<h1>Documentation of Klingon</h1>
</header>
<nav>
<ul>
<li><a href="#text-1">Text 1</a></li>
<li><a href="#text-2"><mark>Text 2</mark></a></li>
<li><a href="#text-3">Text 3</a></li>
</ul>
</nav>
<main>
<h2>Text 2</h2>
<section id="text">
<!-- klingon interlinear goes here-->
</section>
</main>
<aside>
<h3>Other stuff</h3>
</aside>
<footer>
<p>Other stuff</p>
</footer>
<script src="clone-interlinear.js"></script> /* again, ignore this */
</body>
</html>
The
<script>
tag and the@import
in the<style>
are just putting that silly sample Klingon “text” in (with the same repeated sentence). We’re just interested in the high-level content here.
Without CSS
So, if we look at that page without doing any layout CSS
, it just looks like this (check it out here):
Not a bad layout, but not a holy grail. We need to “lay out” the tags in this page into a holy grail. Okay, deep breath, here comes some Holy Grail CSS
:
body {
display: grid;
gap: 1em;
grid-template:
"banner banner banner " auto
"sidebar-1 content sidebar-2 " 1fr
"fine-print fine-print fine-print" auto
/ 1fr 5fr 1fr;
}
body header { grid-area: banner; }
body nav { grid-area: sidebar-1; }
body main { grid-area: content; }
body aside {grid-area: sidebar-2; }
body footer { grid-area: fine-print; }
And that gives us this (you’ll probably want to follow that link because the embed is going to get a little tweaked when it’s squeezed into this forum page):
Okay, line by line.
The first line display: grid;
means “we’re going to set up a grid on the <body>
tag.”
The second line gap: 1em
means “put a gutter between the panels in the grid.”
We’ll come back to grid-template
in a sec, but look at the five lines at the bottom. In that part, we’re saying, “go find the selected tags, and ‘move them’ in to the grid declared on their parent.” So for instance, the line
body header { grid-area: banner; }
Means “go look inside the <body>
tag, and find its <header>
child. Then, put it inside the <body>
’s grid cell which has been named banner
.”
The other lines are doing the same thing: “place such and such a tag in such and such a ‘named area’ in the <body>
’s grid”.
So it’s that complicated grid-template
property that’s actually actually defining the <body>
tag’s grid. The syntax takes some getting used to, so what I’m going to do here is just show you why you should care first, then we can talk a bit more about how it works.
Firefox has a nifty tool that helps a lot when you’re working on CSS
grid layouts (more info here), and it will actually overlay area names onto the rendered page. Hopefully this will help you see how that complicated grid-template
rule maps onto the actual document:
So here is a very different presentation of the document:
A few of the changes have nothing to do with CSS
grid per se (I put a flex on the nav links and turned the <h1>
vertical, for funsies). The key point here is that the HTML
has not changed at all. This turns out to be a very powerful thing, because you can create a simple HTML
document and change its display only in CSS
.
The great thing grid-template
is that it’s easy to drastically change the layout of document without changing the HTML
at all. Here’s the Firefox tool again (I renamed one of the areas from sidebar-1
to nav
, btw):
I’m going to wrap this up here, but there’s a lot more to say about layout with CSS
grid. (I didn’t explain how the widths and heights of the columns and rows are set, for example.)
But I hope that the key benefit of grid-areas
is apparent.
And grid isn’t limited to page-level layout — it could easily be adapted to render a complicated dictionary entry, for instance, something like this:
The fact that that’s even possible with CSS
is amazing.
See also: