text-box-trim is usable now: cut the dead space around headings
Line boxes are always taller than the glyphs, so that half-leading above a heading used to be fixed with negative margins. text-box-trim does it properly.
There is one place in typography where everyone has quietly been settling for less: line boxes are taller than the letters.
A font’s ascent and descent are metrics meant for line breaking, not visual boundaries. So a heading with line-height: 1.2 always carries roughly half of “line height minus glyph height” above it. Inside a card, that shows up as “there is no padding here, yet the heading will not sit flush.”
What we did before
Two workarounds, neither good:
- Hand-tuned negative margins.
margin-top: -0.6emand friends. Change the font or the size and it breaks. - Em-based estimates. The same guess, written more politely.
Both bake a font metric into the stylesheet. Swap the typeface and you start over.
What it looks like now
h1, h2, h3 {
text-box-trim: trim-both;
text-box-edge: cap alphabetic;
}
trim-both trims the first and last line box. text-box-edge says where to cut: cap alphabetic means “top edge to the cap height, bottom edge to the baseline”. Those two values cover almost every heading case.
It trims according to font metrics, so different typefaces lose different amounts. That is exactly what I want: I am after optical alignment, not numeric alignment.
Three things to watch
It only affects the first and last line. Line spacing in between is still line-height’s job. They do not conflict — just do not expect text-box-trim to set your leading.
Block-level boxes only. Inline elements have no independent line box edge, so the property does nothing there. To trim a <span>, make it display: block or inline-block first.
CJK font metrics are looser. Latin fonts have a well-defined cap height; CJK fonts often set ascent generously, so the trimmed result can look tighter than you expected. Try it on one heading before rolling it out site-wide.
What I settled on
Headings and buttons only. Not body copy.
If the first line of a paragraph sits flush against the top of its container, it reads as cramped — body text wants that breathing room. A heading or a button is a solid block of colour, and the space above it is noise, not rhythm.
This is the same position I take on text-wrap: balance: typographic properties should fix what the eye sees, not what the numbers table says. And text-box-trim is one of the few properties that genuinely does the former.

Comments
…