🏠 Grid

By Robert Laing

Columns or rows?

Since most of my learning projects have involved solitaire card games, CSS grid layout has been a natural choice. Starting out, I overcomplicated my stylesheets by including things which I subsequently learnt are best done automatically.

My first mistake was thinking I needed to specify both grid-template-columns and grid-template-rows.

Perhaps if you come from a culture with a vertical writing system, working by rows might seem natural. But to me, left to right is an obvious choice, so all I want is columns. The CSS grid module is cluttered with stuff like grid-template-areas which besides overcomplicating things, lead to not following the best practice of Visual order on the page follows DOM order.

I initially gave every grid cell its own CSS block stipulating its grid-column and grid-row. With more experience I realized if I simply set the number of columns, the tracks — ie rows if working with columns — would take care of themselves.

A 3x3 Tic-Tac-Toe grid

Let’s start with the HTML. I like to follow the convention of labeling my columns alphabetically and my rows numerically, so the ids for my nine cells would look like so:

<main class="tableau">
  <div id="a1">a1</div>
  <div id="b1">b1</div>
  <div id="c1">c1</div>
  <div id="a2">a2</div>
  <div id="b2">b2</div>
  <div id="c2">c2</div>
  <div id="a3">a3</div>
  <div id="b3">b3</div>
  <div id="c3">c3</div>
</main>

I like to use tableau as my wrapper name since it’s mainly for card and other games.

Containers aren’t content

A grid needs a container (aka wrapper) defined either display: grid or display: inline-grid. Only the direct children of this container are seen as cells, something that tripped me up initially.

.tableau {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

Firefox’s inspector tool helps show what’s going on.

This is all we need to get 3 equally spaced colums with 3 rows.

Sizing Cells

My next step is to make all the cells in my grid squares. Here the relatively new orientation CSS media feature along with the var help me make the most of whatever screen real estate my site appears on:

@media (orientation: landscape) {
  :root {
    --side: 30vh;
  }
}

@media (orientation: portrait) {
  :root {
    --side: 30vw;
  }
}

.tableau {
  display: grid;
  grid-template-columns: repeat(3, var(--side));
}

.tableau > div {
  border: 1px solid #999999;
  border-radius: 3px;
  aspect-ratio: 1 / 1;
}
Now I have squares, but I haven’t got things centred.

Horizontal Alignment

I’ve personally found the difference between justify-content, justify-items, and justify-self hard to understand.

Through trial and error, I found adding justify-content: center; to the .tableau {} stanza did the job of horizontally centering the 3x3 grid.

Centering the “content” as in text of the individual cells turned out to be tricky. Rather than justify-, using text-align by adding text-align: center; to either .tableau {} or .tableau > div {} got me this:

All centred horizontally.

Vertical Alignment

This is done with align-content, align-items, and align-items, not to be confused with text-align which works horizontally while vertical-self is for vetical text movement.

If, as in this case, I want to use both justify-content: center; and align-content: center;, there’s the shorthand place-content: center;.

.tableau {
  display: grid;
  grid-template-columns: repeat(3, var(--side));
  place-content: center;
}

.tableau > div {
  border: 1px solid #999999;
  border-radius: 3px;
  aspect-ratio: 1 / 1;
  text-align: center;
  align-content: center;
}
align-content works on the text vertically, but justify-content doesn’t work on text for some reason.