text-box-trim: Removing Excess Line Spacing With Precision
AI generated
{ }
@
CSS · Typography · Layout Precision
text-box-trim in CSS
Finally removing the invisible space above and below text cleanly

Every line of text in a browser carries invisible space above and below the actual letters, a side effect of font metrics reserved for line spacing. With text-box-trim and text-box-edge, that space can be removed precisely, without the fragile negative margin tricks that had to be recalibrated every time a font changed.

15 min read text-box-trim · text-box-edge CSS Text Level 4

1. The problem: invisible space above and below every text block

Anyone who has tried to center a headline or a button label perfectly knows the phenomenon: no matter how carefully padding and line-height are set, the text always looks a touch too high or too low. The cause is not the CSS itself, but the font, which reserves more vertical space per line than the visible letters actually need.

In typography, that reserved space is called leading and by default splits evenly above and below the line. In a single line of text inside a button or a short headline, that surplus quickly adds up to several visible pixels that read like incorrect centering, even though the CSS is technically correct. In the past, only negative margins helped, and they had to be re-measured for every font change.

2. Understanding font metrics: ascent, descent and cap height

Every font file ships its own metrics that the browser uses to calculate line height: the ascent (the height above the baseline up to the tallest ascender), the descent (the depth below the baseline down to the lowest descender), and the line gap, an extra buffer many type designers set generously so multi-line text does not feel cramped. Together these three values produce a font's default line height.

For single-line UI elements like buttons or badges, exactly this line gap buffer is unwanted, because it reserves space that is never visually needed. Cap height, the height of an uppercase letter like H, sits much closer to what the human eye perceives as the actual height of text. It is precisely this gap between technical line height and perceived text height that text-box-trim addresses.

3. Why design tools like Figma measure text differently than the browser

Design tools like Figma display a text frame by default very tightly around the cap height and baseline, without accounting for the font's full line gap buffer. A developer rebuilding a Figma design pixel by pixel therefore regularly finds that the browser text takes up noticeably more vertical space than the design file, even though font size and line height were copied identically. That is not a bug, but a fundamentally different measurement method.

Figma measures text using the font's bounding box values, which are often tighter than the CSS line height the browser is instructed to render. This discrepancy has long been one of the most common sources of design-to-development friction during handoffs. text-box-trim closes that gap by letting the browser align itself to the same reference lines design tools already use for their own display.

4. The text-box-trim property: trim-start, trim-end, trim-both

The text-box-trim property determines on which side of a text block the excess leading space is removed. The value trim-start cuts the space above the first line, trim-end cuts the space below the last line, and trim-both removes both at once. The default value none behaves as before and changes nothing about the familiar behavior.

It matters that text-box-trim only affects the outer edges of the whole text block, not the spacing between individual lines inside a multi-line paragraph. Line spacing within a paragraph therefore stays untouched, only the first and last visible edge of the block gets trimmed. That makes the property useful specifically for containers whose outer dimensions should match the text exactly, without hurting the readability of multi-line paragraphs.


/* Base syntax: remove leading above AND below */
.card-headline {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

/* Trim only above, e.g. when spacing to the next
   element below is still desired */
.section-title {
  text-box-trim: trim-start;
  text-box-edge: cap text;
}

/* Shorthand: text-box combines trim and edge */
.hero-title {
  text-box: trim-both cap alphabetic;
}

5. text-box-edge: cap, ex, text and alphabetic as reference lines

While text-box-trim defines which side gets trimmed, text-box-edge defines which reference line the cut is aligned to. The value cap cuts the top at the top of uppercase letters, ex cuts at the top of lowercase letters like x, and text follows the full text boundary the font defines, including accent marks.

At the bottom, alphabetic is the most common value, because it ends exactly at the baseline and deliberately excludes descenders like those on g or y. Both values are given as a pair, one for the top and one for the bottom, for example text-box-edge: cap alphabetic. If only one value is given, it applies to both sides equally.


/* Comparing different edge combinations on the same headline */
.edge-cap-alphabetic {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic; /* tightest, most precise cut */
}

.edge-ex-text {
  text-box-trim: trim-both;
  text-box-edge: ex text; /* slightly more generous, safer for accents */
}

/* For multi-language content with umlauts and diacritics,
   "text" as the top edge is the safer choice */
.headline-de-fr {
  text-box-trim: trim-start;
  text-box-edge: text;
}

6. In practice: buttons with precisely centered text

Buttons are the classic use case, because their vertical padding is usually set identically top and bottom, yet the text still appears slightly shifted upward due to the leading overhang. With text-box-trim: trim-both and text-box-edge: cap alphabetic, the actual text height matches the cap height, so symmetric padding also looks symmetric, without any empirically guessed correction values.

The effect adds up especially on small UI elements like chips, badges or tab labels: even a one- or two-pixel difference stands out clearly at a 20-pixel line height. Teams maintaining a consistent design system can define the rule once for all interactive text elements and never need to manually re-tune it for every new button type again.


.btn {
  display: inline-flex;
  align-items: center;
  padding-block: 0.625rem; /* identical top and bottom */
  padding-inline: 1.25rem;
  border-radius: 0.5rem;
  background: #4a1d96;
  color: white;
  font-weight: 600;
}

.btn > .btn-label {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

7. In practice: headlines and hero sections without spacing offset

In large hero headlines with a tight line-height, the leading overhang stands out especially strongly, because font size scales the absolute pixel value of the surplus proportionally. A hero title at 64 pixels can carry several pixels of empty space above the first and below the last line, noticeably throwing off a page's vertical rhythm, particularly when the headline sits inside a tightly tuned grid system.

For multi-line headlines, trim-start on the topmost and trim-end on the bottommost visible text block is recommended, while spacing between the individual lines remains untouched. That preserves the readability of the multi-line text while the spacing to elements before and after aligns exactly with the visual text boundary instead of the font's technical line height.


.hero-headline {
  font-size: clamp(2.5rem, 5vw, 4rem);
  line-height: 1.05;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
  margin-block: 0; /* no more compensation via negative margins */
}

.hero-headline + .hero-lead {
  margin-block-start: 1rem; /* precise spacing without a leading buffer */
}

8. Fallback for browsers without support

Because text-box-trim is a comparatively new property, not every browser in active use supports it yet. Since the property is simply ignored in non-supporting browsers without throwing an error, the layout falls back at worst to the old, slightly more generous look, instead of breaking entirely. Progressive enhancement is therefore given automatically, without any extra effort.

Anyone wanting to minimize the visual difference between supporting and non-supporting browsers can additionally use @supports to check whether the property is available and only then apply small adjustments to padding or margin that would otherwise cause a double offset. For most UI elements, however, the native fallback is entirely sufficient without any extra CSS.


.btn-label {
  /* Base padding for browsers without text-box-trim */
  padding-block: 0.75rem;
}

@supports (text-box-trim: trim-both) {
  .btn-label {
    text-box-trim: trim-both;
    text-box-edge: cap alphabetic;
    /* tighter padding, since the leading buffer is already removed */
    padding-block: 0.625rem;
  }
}

9. Browser support and how it compares to older approaches

Support for text-box-trim and text-box-edge has already landed in modern Chromium and WebKit based browsers, while other engines are working on implementations. Before using it in production, it is always worth checking a current compatibility table, because support for a still-young property can change quickly.

Compared to older approaches like manually calibrated negative margins or JavaScript libraries that read font metrics at runtime, the native property offers three clear advantages: it works independently of the specific font, does not break when the typeface is swapped, and costs no extra computation in the browser, because the metrics are already known while the font is being rendered.

Approach Font-independent Maintenance effort Browser baseline needed
text-box-trim Yes Very low Modern Chromium/WebKit engines
Negative margins by hand No, remeasure per font High All browsers
JS library for metrics Yes Medium, extra dependency All browsers with JS
line-height: 1 as approximation No, imprecise Low, but inaccurate All browsers

Mironsoft

Modern CSS, layout architecture and rendering performance

CSS that stays maintainable instead of breaking with every change?

We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.

CSS Audit

Systematically uncovering specificity issues, cascade conflicts and unused selectors.

Architecture Refactoring

Introducing cascade layers, custom properties and design tokens cleanly.

Performance Tuning

Fixing layout thrashing, expensive selectors and rendering bottlenecks.

10. Summary

text-box-trim: The Essentials at a Glance

Core problem

Fonts reserve more vertical space per line than the visible letters need, appearing as empty space above and below the text.

Solution

text-box-trim: trim-both together with text-box-edge: cap alphabetic removes that surplus precisely, without guessing at negative margins.

Design connection

Figma and other design tools already measure text tightly around cap height, text-box-trim aligns browser rendering with design files.

Fallback

Non-supporting browsers simply ignore the property, an @supports block allows additional fine tuning when needed.

11. FAQ: text-box-trim: The Essentials at a Glance

1What exactly does text-box-trim do?
The property removes the excess leading space a font reserves above the first and below the last line of a text block, without changing the line spacing inside a multi-line paragraph.
2What is the difference between text-box-trim and text-box-edge?
text-box-trim defines which side gets trimmed, trim-start, trim-end or trim-both. text-box-edge defines which reference line of the font the cut aligns to, such as cap or alphabetic.
3Why does text look positioned differently in Figma than in the browser?
Figma measures text tightly around the font's cap height, while the browser by default accounts for the font's full line gap buffer. text-box-trim closes that difference.
4Does text-box-trim affect the spacing between multiple lines of text?
No. The property only affects the outer edges of the entire text block, spacing between individual lines within a paragraph stays unchanged.
5What happens in browsers without support?
The property is ignored, the layout falls back to the familiar behavior with the full leading buffer, without any error or broken layout.
6Which values are most common for text-box-edge?
At the top usually cap for the top of uppercase letters, at the bottom usually alphabetic for the baseline. For text with many accent marks, text as the top edge is often the safer choice.
7For which elements is text-box-trim most worthwhile?
For single-line UI elements like buttons, badges, tabs, and for large hero headlines where the empty space becomes especially visible due to the large font size.
8Can I safeguard text-box-trim with @supports?
Yes, an @supports block checks whether the property is available and lets you fine tune padding or margin separately for supporting and non-supporting browsers.
9Does text-box-trim fully replace negative margins?
For most cases yes, because it works independently of the font and does not need recalibration on every font change. Manual negative margins only remain relevant as a fallback.
10Is there a shorthand for both properties together?
Yes, the text-box shorthand combines text-box-trim and text-box-edge in one declaration, for example text-box: trim-both cap alphabetic.