How to Fix Extra Space Above and Below Text in CSS
Fix extra space above and below text with CSS text-box-trim. See how font metrics and line-height create gaps, choose text-box-edge values, and add browser fallbacks.
The extra space above and below text comes from two sources: the font’s built-in vertical metrics, and the half-leading that line-height adds (or removes) on each side of the line. The native CSS fix is text-box: trim-both cap alphabetic.
You set line-height: 1.1, removed every margin, and the heading still sits in a box taller than its letters. So you added a negative margin, tuned it until it looked right, and moved on. Then the brand font changed.
This article covers where that space comes from, why negative margins can’t remove it reliably, and how text-box-trim, text-box-edge and the text-box shorthand trim it on headings and buttons. It ends with a fallback for older browsers.
Key Takeaways
- Extra space around text comes from the vertical room a font reserves for its tallest and deepest glyphs, plus the leading that
line-heightadds or removes, which CSS splits equally above and below each line. text-box-trimchooses which edges to trim (none,trim-start,trim-end,trim-both), andtext-box-edgechooses the line each edge is trimmed to.text-box: trim-both cap alphabetictrims the top to cap height and the bottom to the baseline, which matches how most designs measure spacing.text-box-edgedoes nothing unlesstext-box-trimis set to something other thannone.text-box-trimis not inherited, so declare it on each element you want trimmed, not onbody.
The Symptom: A Gap That Padding Doesn’t Explain
A heading with zero padding, zero margin and a tight line-height still shows empty space above its capitals and below its baseline. DevTools shows the content box is taller than the visible letters, and nothing in your stylesheet accounts for the difference.
The usual patch is a negative margin found by trial and error:
h1 {
line-height: 1.1;
/* Tuned by eye for one font; wrong for any other */
margin-block: -0.2em -0.15em;
}
Those values are illustrative placeholders. They aren’t derived from anything, and that is the problem.
Why Is There Extra Space Above and Below Text?
The extra space above and below text has two causes, font metrics and half-leading, and both belong to the text rather than the box model.
First, a font sets aside vertical room for all of its glyphs, from tall capitals to the tails of letters like g and y. How much room it sets aside varies from one typeface to the next, as MDN’s text-box-trim reference notes, so the same font-size gives a taller or shorter line box depending on the font.
Second, line-height adds leading. The CSS 2.1 specification on leading and half-leading defines leading as the difference between the line-height and the font’s ascent plus descent. Half of it goes above the glyphs and half goes below. Many fonts have an ascent plus descent larger than 1.1em, so at line-height: 1.1 the half-leading is often small or even negative. Either way, the empty space the font’s own metrics leave above the capitals and below the baseline is still there.
Every typeface reserves a different amount of vertical space, so a negative margin tuned for one font is wrong for another. That includes the fallback font shown before a web font loads, an issue that also drives font-related layout shift. If you replay a session where the web font arrives late, you can see the frame where the font swaps and a magic-margin heading jumps.
How Do You Fix the Gap With text-box-trim?
text-box-trim chooses which edges of a text block get trimmed, and text-box-edge chooses the line each edge is trimmed to. text-box-trim accepts four keywords:
none: the initial value. Nothing is trimmed.trim-start: trims the over (top) edge.trim-end: trims the under (bottom) edge.trim-both: trims both edges.
Here is the same heading, with the margin hack replaced:
h1 {
line-height: 1.1;
text-box-trim: trim-both;
text-box-edge: cap alphabetic;
}
With text-box-trim applied, the top edge of the box now sits at the top of the capitals and the bottom edge sits on the baseline. The extra space is gone for any font, because the browser reads the positions from the font rather than from your guess.
The text-box shorthand combines both properties in one declaration. These two rules are equivalent:
h1 {
text-box: trim-both cap alphabetic;
}
/* Same result: an omitted trim keyword means trim-both */
h1 {
text-box: cap alphabetic;
}
Which text-box-edge Values Matter?
For horizontal text, two edge pairs cover nearly every case: cap alphabetic and ex alphabetic. text-box-edge takes two keywords: the first sets the over edge and the second sets the under edge.
| Keyword | Edge | Trims to |
|---|---|---|
text | over or under | the font’s text edge (this is what the default auto resolves to) |
cap | over only | the top of the capital letters |
ex | over only | the x-height (top of short lowercase letters) |
alphabetic | under only | the alphabetic baseline |
cap alphabetic matches how designers usually measure the space around a heading or label: from cap height to baseline. Use ex alphabetic when the text is mostly lowercase and the x-height is the visual top:
.lowercase-label {
text-box: trim-both ex alphabetic;
}
Three rules catch most people out:
text-box-edgehas no effect by itself. Nothing is trimmed unlesstext-box-trimis set to something other thannone.- In the
text-boxshorthand, leaving out the trim keyword meanstrim-both, and leaving out the edge meansauto. The keywordnormalis equivalent tonone auto. - Neither
text-box-trimnortext-box-edgeis inherited. Setting them onbodydoes not trim the headings or buttons inside it. Declare them on each element, or in each component’s base styles.
Centring a Button Label With text-box
A padded button with equal top and bottom padding often shows its label sitting off-centre. The padding is equal, but the font’s internal space above the capitals and below the baseline is not, and you see that difference as extra padding on one side.
.button {
padding: 0.75rem 1.25rem;
}
Trimming the label box to cap height and baseline makes the padding the only space between the text and the button edge:
.button--trimmed {
padding: 0.75rem 1.25rem;
text-box: trim-both cap alphabetic;
}
With a label such as “Submit”, the space above the capitals now looks the same as the space below the baseline. The CSS Inline Layout spec lets text-box-trim apply to block containers, multi-column containers and inline boxes, but browsers differ. Per Mozilla’s intent to ship, Firefox and Safari trim inline boxes and Chromium does not. Trimming also has no effect on a flex or grid container, so give the button display: inline-block, or put the trim on a label element inside it. Because the bottom edge is trimmed to the baseline, descenders in letters such as g, p and y extend into the padding. That is the expected typographic result, not a bug.
Browser Support and Fallback
MDN marks text-box as Baseline 2026, newly available since August 2026, and notes that it may not work in older devices or browsers. Browsers that don’t support it ignore the declaration and render text with normal font spacing. The fallback is the untrimmed layout: not broken, just less precise. If a design depends on the old compensating margins, keep them only for those browsers with an @supports feature query:
h1 {
text-box: trim-both cap alphabetic;
}
@supports not (text-box: trim-both cap alphabetic) {
h1 {
/* Old per-font patch, kept only where text-box is unsupported */
margin-block: -0.2em -0.15em;
}
}
Conclusion
The gap around text is font metrics plus half-leading. A negative margin only hides it, and only for one typeface. Replace those margins with text-box: trim-both cap alphabetic on each heading and label component, move any legacy margins behind @supports not, and check the result with your fallback font as well as your web font.
FAQs
Does text-box-trim change the spacing between lines in a multi-line paragraph?
No. On a block container, text-box-trim only touches the top of the first line and the bottom of the last line. The half-leading between wrapped lines stays as it is, so line-height still controls the spacing inside the paragraph. Only the outer edges of the block move in to the cap height and the baseline.
Why not just set line-height: 1 to remove the extra space?
Setting line-height: 1 only changes the leading. The font's own reserved space above the capitals and below the baseline stays, so the box edges still don't line up with the cap height or the baseline. It also tightens the spacing between wrapped lines. text-box-trim trims only the outer edges to font metrics and leaves line-height free to control readability.
Does trimming with text-box affect the layout of surrounding elements?
Yes. text-box-trim moves the element's content edges in to the chosen metrics, so the element takes up less block space. Margins, flex and grid gaps, and neighbouring elements are then measured from the trimmed edge, not from the font's reserved space. That is why spacing tokens become visually accurate once trimming is applied, and why removing old negative margins matters.
How do I detect text-box support in JavaScript?
Call CSS.supports('text-box', 'trim-both cap alphabetic'). It returns true in browsers that accept that declaration and false in browsers that don't. It runs the same test as the @supports rule in CSS, so you can use it to decide at runtime whether to apply compensating margins or to log which rendering path a user gets.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Star on GitHub12k