A flexible solution for centering icons & text
Modern CSS units provide a solution to a long-standing layout pattern.
There’s a small layout pattern that I’ve encountered many times throughout my career. I don’t know if there’s a name for this pattern, but it’s reminiscent of the “media object” of yore.
It consists of a small icon or illustration and a line of text. The icon is usually slightly taller than the line of text, and the text is centered to the icon.
The markup for this would likely be something like:
There are any number of ways to center things in CSS these days, so that’s not a problem. The first wrinkle that we hit is that the text could potentially run two or more lines and we want the first line to remain center-aligned to the icon.
This can be solved with some margin or padding tweaking, but this is where I’ve always felt unsatisfied with the end results. Getting something like the above that matches a mockup is clearly doable, but only at the exact font size specified. If the font size increases it throws off the measurements. Brittle layouts are no good, and for accessibility coverage you want to be sure text can be increased by 200% without issue.
The first sign of hope comes from the new lh
CSS unit. Available in all major browsers since November 2023, this unit is based on the element’s current (computed) line height. With the icon’s container set to the same height as a line of text, that keeps things centered how we want, no matter the text size. If the icon is a fixed height, it’s possible it could end up being taller than the text dimension allows. To account for this, we have the wrapping element aligning its items to the center; the icon will overflow but remain centered within its parent.
This all works because the line-height
affects the “text box” of the text — it’s the space above and below a line of text, not just the space between baselines — and the text itself is more or less centered within this box (depending on the font in use). Which brings us to the next wrinkle…
text-box-trim
(in earlier spec drafts this was called leading-trim
) is a proposed CSS property that removes the extra space from around text. It’s not available in many browsers yet, but there are ways to achieve the same result available today, although they require some careful calculations with various font metrics. Very helpful for getting more precise spacing around text and other elements, but it means the previous solution no longer works.
We still have the same amount of space between lines of text, but the centering of the first line is off because the extra space above is removed. Luckily, the solution is simple: another recent CSS unit, cap
, was added to all major browsers in December 2023. Similar to lh
, this gives us a measurement based on the cap height of the font in use — to which text-box-trim
sets our first line!
Now we have two solutions to this common pattern that give us the visual results we want while also adapting to different themes or user settings automatically. What a time to be alive (and writing CSS)!