CSS text-spacing-trim: Clean CJK and Quote Punctuation

CJK and quote spacing without manual kerning

Full-width punctuation in CJK and quoted text ships with extra space baked into the glyph. The old fix used negative margins and text-indent per element. text-spacing-trim hands that decision to the font.

Old way 13 lines
.prose p:first-letter   {  margin-inline-start: -.25em;}.prose p   {  text-indent: -.25em;  padding-inline-start: .25em;}.prose q::before   {  margin-inline-start: -.2em;}.prose q::after   {  margin-inline-end: -.2em;}
Modern
1 line
.prose   {  text-spacing-trim: trim-start; }
Limited availability 69% global usage

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Not ready for production without a fallback.

123+
123+
opening punctuation no longer indents the first line
without

「品質を最優先に」考えるなら、まず印刷機を見直すべきだ。

with text-spacing-trim

「品質を最優先に」考えるなら、まず印刷機を見直すべきだ。

text-spacing-trim: trim-start

One declaration

Trim the extra glyph padding around full-width punctuation with a single rule. No negative margins, no text-indent, no pseudo-elements per quote.

Font-aware

The browser reads the OpenType cv-spacing or chws feature in the font and trims accordingly. Works across mixed CJK and Latin runs without breaking either.

Granular keywords

Use trim-start to clean only leading punctuation, trim-both to also trim at line ends, or space-first to keep the first occurrence and trim the rest.

Lines Saved
13 → 1
No per-element CSS
Old Approach
negative margins
text-indent hacks
Modern Approach
text-spacing-trim
Font-aware trimming

How it works

Full-width punctuation (Japanese 「 」, Chinese 「 」 and 「 」, full-width parentheses, em-dashes in CJK fonts) ships with extra space inside the glyph box. When a paragraph starts with one of these characters, the line begins with a visible indent. When two punctuation marks meet, the gap between them doubles. Designers used to fight this with per-element rules: negative margin-inline-start on the first letter, text-indent: -.25em on the paragraph, negative margins around q::before and q::after. It scaled poorly and broke whenever the content changed.

The text-spacing-trim property tells the browser to trim that extra glyph space based on font metadata. The font ships the rules (via the OpenType chws or halt feature) and the browser applies them. trim-start handles the most common case: opening punctuation no longer indents the first line. trim-both also trims trailing punctuation at line ends. space-first keeps the first character's space and trims later ones.

ESC