The other day, Rachel Andrew’s new book The New CSS Layout was in the mail. On the same day, Microsoft put out their latest Windows 10 update. Coming with it: Edge with full support for CSS grid. Now was the time for me to do something proper with CSS grid.

Following is an approach to layout articles that goes beyond the one boring centered column of content with a maximum width. Who’s not written something like this before:

  .content {
  max-width: 1000px;
  margin-right: auto;
  margin-left: auto;
}

Some Content is not Like The Other

Sometimes, content needs more room. The block of code that unfortunately triggers a horizontal scrollbar, the beautiful picture you took during that special winter walk last year, the outstanding quote that just won’t let you go.

With grid, we now have access to a powerful tool, that lends a couple of hands with our task. In my opinion, one of the big advantages of grid over the hacks we used to do grid-like layout with, is the ability to maintain correct and clean HTML. We can structure our content properly and put a grid on top of it. No wrapper elements that form columns or any of that.

Demo

It’s best to have a look at this in a separate window. It demands some free space and resizing to see what changes between the break points I chose.

1, 2, 3 Columns

On smaller screens, the layout is the same old one column layout we’re used to. Nothing fancy there. Going above 600 pixels, we see the first change. An article is now split into two columns. One for the main content and one with additional room for wider content. Generally, content spans the width of the main content column. However, if more space is needed, it can grow wider and span the full available width. Starting at a viewport width of 1400 pixels, a third column is introduced. It allows wide content to take up even more space.

This leaves us with a 3-column-grid, the center column being for main content, and two side columns for wide content. The side columns can also be used for related content—content that doesn’t belong to the general flow of the article but rather serves as additional content.

How about displaying footnotes there? Or the image of a person you referenced in its related main content? Your choice.

The Grid

Implementing this was rather straight forward. Grid does all the heavy lifting. Let’s start with the basic setup.

  .post {
  display: grid;
  grid-column-gap: 1.5rem;
  align-items: start;
}

This doesn’t do much. So far, we would get a gap between columns, if there were more than one. All content in a column would also align to the top of it, which right now it already does.

Next up, we’ll define the template for columns. We don’t actually define a template for rows. We let grid figure that out for us.

  .post {
  ...
  grid-template-columns: 3fr 1fr;
}

With this template, we divide an article into two columns. The first (read left-most, if you’re using a LTR language; right-most otherwise) column is 3fr wide, the last column is 1fr wide. That means 3 pieces of a whole and 1 piece of a whole. In this case, a whole would be 3 + 1 = 4. We end up with columns being 3/4 and 1/4 or 75% and 25% of a whole wide. In other words, fr stands for fraction.

Now we use some magic. If that’s fine for you. We give the space before and after columns names. This space are the grid tracks. A grid line is the actual column or row, a grid track is the space between columns and rows. It looks like this:

  .post {
  ...
  grid-template-columns:
    [full-start main-start] 3fr [main-end side-start] 1fr [side-end full-end];
}

So, wait a second. That doesn’t look as nice anymore, does it? Takes a bit of getting used to. Don’t worry. What we did is mark where some special columns start and end. Remember when I talked about main content, content that spans over the full width and side notes? With these names, we now can play sorting hat and put our content into its place.

If you recall, I something about content generally falling into the main category.

  .post > * {
  grid-column: main-start / main-end;
}

Done. All content inside an article now spans across the main column we just defined. See, I got a bit lazy here with my catch-all approach by using the universal selector. Because now we will override this for content that should span the full width. To write more robust CSS, it would be better to target exactly what we want (e.g. h1, h2, h3, h4, h5, h6, p, ...). But that’s a demo. I can do what I want. Also, we need to be explicit with the following exceptions anyway.

  .post > pre,
.post > figure,
.post > blockquote,
.grow-to-full {
  grid-column: full;
}

Note that I used a different syntax now? This is possible because we used the *-start/*-end scheme for naming the grid tracks. With that, one can short *-start / *-end to *. Neat.

Our exceptions include code blocks, figures and block quotes and, well, anything we want. We can just add the grow-to-full to the markup to let a regular paragraph grow wider. This allows us to have exceptions of exceptions.

Lastly, the promised side notes, sometimes also called boxouts.

  .post > .side-note {
  grid-column: side;
}

.post > .has-side-note {
  grid-column-end: main-end;
}

The second ruleset allows wide content to have a side-note as well.

That’s it. I think grid is amazing. It gives us so much flexibility over how we lay out content inside articles. These are truly exciting times for web technologies.


1,609 0 18