Perfectly Aligned Image Captions with CSS Grid & subgrid
It’s sad to think that my whole ordeal with images and Netlify Large
Media began because of
Flexbox. I am an unabashed admirer of
Flexbox. I like to say most of the work in modern CSS is setting display: flex
and tweaking
the rest. However, Flexbox’s purpose is to lay things out in one axis. A single-row list is easy.
Vertical centering is easy. You might think image captions are too. You’d be wrong.
On A Place For My Head, images are either standalone or part of a group. Both standalone images and entire groups can be floated to either side. Both can have captions. An image with a caption can be part of a group with a caption. Here are simplified versions of some of the permutations of HTML:
HTML<!-- A single image -->
<a href="/full/sized/image.png">
<img src="/smaller/image.png" alt="">
</a>
<!-- A single image with a caption -->
<a href="/full/sized/image.png">
<figure>
<img src="/smaller/image.png">
<figcaption>An image</figcaption>
</figure>
</a>
<!-- A group containing three images of which the second has no caption -->
<p>
<a href="/full/sized/image/1.png">
<figure>
<img src="/smaller/image/1.png">
<figcaption>Image 1</figcaption>
</figure>
</a>
<a href="/full/sized/image/2.png">
<img src="/smaller/image/2.png">
</a>
<a href="/full/sized/image/3.png">
<figure>
<img src="/smaller/image/3.png">
<figcaption>Image 3</figcaption>
</figure>
</a>
</p>
<!-- A group containing two images with a single caption for the entire group -->
<figure>
<a href="/full/sized/image/1.png">
<img src="/smaller/image/1.png">
</a>
<a href="/full/sized/image/2.png">
<img src="/smaller/image/2.png">
</a>
<figcaption>A caption for the entire group</figcaption>
</figure>
The general structure of an image group is figure > a > figure > img
. It’s trivial to arrange the
figures horizontally on wider screens with Flexbox, two to a row, by setting display: flex
on the
figure
(or p
) and widths on the individual images. Since these images can have differing aspect
ratios as well as captions, though, this can produce displeasing
results (and don’t even think about having
multi-line captions):
The solution is to use CSS Grid, which controls layout in two dimensions. Specifically, it requires the shiny new subgrid layout. By setting each intermediary level to use subgrid, we can ensure the captions are aligned with each other irrespective of the shape of the images. My proof-of-concept worked beautifully:
However, when I tried to apply the same principle to the site locally, I saw interesting results:
Eventually, I realized this was because of one particular line:
CSSgrid-auto-rows: auto auto;
I left the heights of the rows up to the renderer, which based them on the intrinsic sizes of the images… that is, the original sizes, thousands of pixels tall and long. The moment I switched to appropriately-sized versions, the rows took on normal heights and the whitespace vanished.
This was the inciting incident for the Netlify Large Media saga, at the end of which I had unintentionally and unnecessarily lost irreplaceable historical data. I’m going to tell myself the difference is worth it: