New Dec 19, 2024

Why I’m excited about text-box-trim as a designer

More Front-end Bloggers All from Piccalilli - Everything View Why I’m excited about text-box-trim as a designer on piccalil.li

I’ve been excited by the potential of text-box-trim, text-edge and text-box for a while. They’re in draft status at the moment, but when more browser support is available, this capability will open up some exciting possibilities for improving typesetting in the browser, as well as giving us more control of alignment and internal spacing in our components, such as a button.

Daniel Schwarz wrote a great deep dive into the current proposal for these two CSS properties, but in this article I’d like to give you an even more solid understanding of the problem this new CSS capability is solving.

Aligning text on the web has historically involved a level of compromise. Much of this is down to how fonts render in the browser, and inconsistencies in how different fonts take up space within their text box.

The word ‘Typography’ set in large bold type, with the text box outlined, demonstrating the extra space within the text box, above and below the visual height of the text

This diagram shows the text box for Moderat Extrabold, the headline font we use for Piccalilli. The box is cropped pretty tight horizontally, but vertically there’s a lot of space above and below, which can make typesetting tricky, especially when combining fonts which may have different amounts of space above and below (which we’ll come to later).

What makes up all that extra space? There are a lot of factors involved, and the spacing can differ greatly from font to font. Let’s break it down.

A primer in font metrics

It’s good to have some context for the metrics that influence the spacing within a font. Here’s a visual breakdown of the vertical metrics within Moderat Extrabold.

The word ‘Typography’ set in large bold type, with lines showing the baseline, x-height, cap height, ascender line and descender line

The ascender and descender lines mark the boundaries of the font’s geometry. In general, ascenders and descenders will extend to these lines. Letters with curved or angled forms generally overshoot these lines ever so slightly, to achieve visual balance alongside their straight-edged counterparts.

As you can see below, in some fonts, certain ascenders will sit below the ascender line. Check out the lowercase “t” here in Moderat below, for example.

The letters ‘Hy, th’ set in large bold type, with lines showing the baseline, x-height, cap height, ascender line and descender line. The letter ‘t’ in Moderat here sits lower than the cap height

The cap height, as the name implies, marks the height of a font’s capital letterforms. It often sits below the ascender line, but in some fonts the cap height and ascender line can be at the same height.

The take away here is that the spacing dynamics within the characters of your text will differ depending on the font you’re using.

Font sizing

In digital type, font metrics are all relative to font size. Let’s imagine we give a paragraph element a font-size of 1em in our CSS. What aspect of this font is 1em tall? The short answer is we don’t know because the font size does not give us any reliable information on the size of the characters within a font or the metrics within it.

To help understand why, it’s helpful to know that when a type designer is creating a font, they’ll design each character within a box known as an em square, which acts as a grid container for the glyph. This is not the same unit we’re applying in CSS, as the browser calculates em values differently than traditional type design. If our paragraph with font-size: 1em renders at 16px, what’s happening internally within the font is that its em square container is being scaled to 16px tall. Inspect the element in the browser, and with a line-height of 1, the element’s bounding box will be 16px tall. But within that box, the positioning and sizing of the actual letterforms are totally up to the font designer, which is why they can vary so much from font to font.

FYI

The `16px` value is an approximation and based on a presumption that your operating system font size has not been changed from its default value.

Although the font size set by us designers tells the software at which size to render the em square, the type design within that em square can theoretically sit wherever the type designer wants it to. The horizontal and vertical positions of the marks that make up any given letterform are very much an arbitrary decision, so, like many things in type and typography, there are no hard-and-fast rules.

Elliot Jay Stocks

This variability is a key consideration when swapping a font, or using multiple fonts in a project. Check out Elliot Jay Stocks’ write-up for Google for more on this.

The word ‘Apples & Oranges’ set in large bold type in Inter above, and Josefin Sans below, with lines showing the baseline, cap height and descender line, and the text boxes outlined. The spacing differences are clear, with each font sitting at a different vertical position within the text box. Inter’s descenders extend outside the text box, but in Josefin Sans’, both the ascenders and descenders extend outside the text box

Above is a comparison of Inter with Josefin Sans set at the same font size and a line-height of 1.0. The text box is marked in red, and the cap height, baseline and descender line in yellow. As you can see, whilst both text boxes are the same height, Josefin Sans’ baseline sits higher than Inter’s, and the spacing above and below the two fonts is markedly different. Notice that both fonts include ascenders and descenders that extend out of their text box too.

To show an example that takes this to extremes, here’s Zapfino. Check out those swashes which are miles out of the text box. What’s also interesting here is that the cap height sits a way outside of the text box too. Thinking back to the flexibility type designers can employ in designing their fonts within the em square, this example really demonstrates that sizing and spacing within a font can be a bit of a wild west at the extremes.

The word ‘Jackfruit’ set in the Zapfino font, with lines showing the baseline and cap height, and the text box outlined. The capital letters and ascenders and descenders extend out of the box by a significant amount

Leading

The final piece of the puzzle in understanding how text boxes are calculated in CSS is line-height, or “leading” in typographic terms. In traditional metal type, the spacing between lines of text was set via lead strips. These spacer strips were added between lines. The CSS approach to leading works a little differently, in that spacing is added both above and below each line of text. You can think of this as a kind of “half leading”.

With line-height set to 1.0, an element’s text box height will equal its font-size (multiplied by the number of lines of text if it wraps). In the case of our paragraph example, the text box will be 16px tall. Change the line-height to 1.5, and the text box grows to 24px tall, with 4px of leading added above and below. And if you set a fixed line height rather than a relative one, the browser just sets the text box to match the line-height and distributes any space evenly above and below.

On the left, the letters ‘Aa’ set in large bold type at a line-height of 1em, with the text box outlined. On the right, the same letters set at a line-height of 1.5em, with annotations marking the font height of 1em, and half-leading above and below of 0.25em, totalling 1.5em

Let's see how text-box-trim will help us

When you break it down, the extra space within an element’s text box is quite simple to understand. Just take the font size and add half the leading above and below. But as we’ve learned, it’s the extra space within the font itself, and the variability of the character sizing and positioning within different fonts that makes this much more tricky to work with in practice.

The word ‘Typography’ set in large bold type, with lines showing the baseline and cap height, and annotations marking the font visual height, font height, line-height and half-leading above and below

With text-box-trim we gain control over which boundary line text boxes are cropped to, and finally we can trim away this extra space to work with a font’s actual visual height.

One of the ways we’re planning to use this feature to improve typesetting at Set Studio is within our favoured fluid spacing system. We use a spacing scale that’s based on multiples of a base unit, which we combine with utilities like flow to keep a sense of rhythm between all the elements on a page. But in practice, the extra space within text boxes has meant we’ve had to let go of the idea of creating true vertical rhythm for text elements within our spacing system.

We’re pragmatic and happy to live with this for the sake of creating designs that work with the medium of the browser. But when a little bit more support comes for text-box properties and we can trim away that unwanted extra space, we’ll be all over it, as a progressive enhancement.

.prose :is(h2, h3, h4, p, ul, ol, li, blockquote, figure) {
  text-box: cap alphabetic;
}

FYI

We’re using the shorthand property here.

Here we’re trimming text elements within .prose content to the cap height and baseline. Our prose now nicely follows our fluid spacing rhythm!

Applying a trim like this could — depending on the font as we’ve discussed — cut a fairly severe amount of spacing from between your text elements, so it’s very likely you’ll want to increase the spacing when this is applied. Hence our slight trepidation about using text-box in production yet.

It’s worth bearing in mind that design tools like Figma treat text spacing in a very similar way to the browser, with leading above and below, so spacing decisions during design will have been made with this extra spacing in place.

To account for this, we can bump the flow space up a step within our spacing system. Because our CSS is affecting wider elements via the change to --flow-space, we’re going to fence the code in a @supports query now because we only want this to apply if text-box-trim is available to us.

@supports (text-box: cap alphabetic) {
	.prose :is(h2, h3, h4, p, ul, ol, li, blockquote, figure) {
	  --flow-space: var(--space-l);

text-box: cap alphabetic } }

Figma has a setting that lets you toggle ‘vertical trim’ for text elements, under the additional typography settings. If you’re planning to use text-box in your code, it’s a good idea to design with this setting on. And test designs in the browser with and without trimming the text box to make sure both the reading experience is solid in each case. Readability is more important than perfect vertical rhythm.

Screenshot showing Figma’s ‘Cap height to baseline’ setting, within ‘Typography > Basics > Vertical Trim’

Another good example of where these new CSS properties will help us improve our designs, is making precise vertical alignment of text and imagery like this design from Marko Cvijetic on Dribbble much more easily achievable.

Article layout design by Marko Cvijetic, featuring various image elements with text precisely aligned vertically

One of the most common use cases for a lot of us is visually centering text within elements like buttons or notifications. This is especially handy for fonts that have awkward spacing like Josefin Sans.

Two buttons side by side, one with text set in Josefin Sans with a default text-box where the text is not visually centered, the other with visually centered text achieved by trimming to the cap height and baseline

There are plenty of creative uses for text-box-trim too. In this design I placed headings with their baseline flush against sections below using negative margin, like this:

.footer-heading {
	margin-bottom: calc((var(--space-3xs) + 0.072em)* -1);
}

It’ll be nice to be able to achieve effects like this without resorting to magic numbers, thanks to text-box-trim.

A website footer that has a heading, “Talk to us”, which is perfectly aligned with the box below it

I used a similar approach to add baseline borders to headings in another project, but couldn’t achieve perfect baseline alignment in Firefox. With text-box-trim this effect could be layered in as a progressive enhancement, with the lines only added where the browser supports it.

Screenshot showing a border effect added to a the baseline of a heading on the WePioneer website

I’m excited to see what people make with these new CSS properties once they ship!

Latest support

See the latest browser support for text-box-trim, text-box-edge and text-box here. As with all newer CSS specifications, the syntax might change as it evolves, so I recommend keeping an eye on the discussions.

Scroll to top