Why Your AI Agent’s Line-Height Is Clipping Devanagari — And How to Fix It
Your agent just set line-height: 1.4 on a Hindi hero heading and clipped every matra off the glyphs. Arabic tashkeel collide with their base letters, and a Chinese title overflows because the engine treats twelve unbroken ideographs as one long Latin word. None of that is a rendering bug — it’s Latin typography defaults applied to scripts they were never tuned for. Agents don’t need taste to fix this; they need per-script, computable rules.
What Agents Can Perceive
Everything a script-aware check needs lives in the DOM: font-family, line-height, letter-spacing, and word-break from computed styles, the lang attribute on ancestors (MDN), and each text node’s Unicode range. Join those signals and typography stops being opinion — it becomes lint. That answers this blog’s first sub-question: perception is sufficient.
Four Computable Rules
1. Devanagari (Hindi, Marathi)
- Problem: Latin-tuned leading clips matras and stacked conjuncts above the shirorekha.
- Check:
line-height >= 1.8on any element whose text nodes are predominantly Devanagari (U+0900–U+097F, orlang="hi"). - Basis: The W3C Devanagari requirements document above-base matras and stacked conjuncts extending past Latin ascender heights — the geometry tight leading destroys. India’s multilingual reality — Tamil users prefer formal layouts, Marathi users prefer pictures and easy menus (RankRaze) — makes per-script detection a precondition. The 1.8 floor is our proposed check, set high enough to clear that documented geometry.
2. Arabic
- Problem: Tashkeel sit above and below the baseline and collide when leading is tuned to Latin x-heights.
- Check (proposed):
line-height >= 1.6on Arabic runs, plus a coverage assertion: every Arabic codepoint resolves in the final computed font. - Basis: The W3C Internationalization activity maintains script-layout requirements covering Arabic; absent a published numeric minimum there, 1.6 is an explicitly proposed check, kept conservative.
3. Chinese and Japanese (CJK)
- Problem: CJK has no inter-word spaces; default don’t-break-inside-words logic overflows containers, and agents “fix” it by shrinking type.
- Check:
word-break: break-all(MDN) oroverflow-wrap: break-word(MDN) on CJK containers;line-height >= 1.7(proposed check) for Japanese. - Basis: The Unicode Line Breaking Algorithm (UAX #14) permits breaks between ideographs, so wrapping is standards-compliant. Density is convention, not bug: Japanese web design’s “text avalanche” and Chinese “busy = credibility” — QR codes, super-app integration (Alibaba’s 2026 guide) — mean tight pages are intentional; wrapping and readable leading must both hold.
4. Korean
- Problem: Hangul blocks are dense and squared; letter-spacing inherited from Latin rules distorts them.
- Check (proposed):
letter-spacingexplicitly declared, never inherited, on Korean runs;font-size >= 15px;line-height >= 1.6. - Basis: Creative Bloq documents Korea’s pop-futurism wave, and the Naver-versus-Kakao split means two legitimate “normal” references — declare a baseline, don’t inherit one. Noto Sans KR is a coverage-safe default. All three numbers are proposed checks.
Font Stacks Are Not Portability
One stylesheet renders Arabic through Geeza Pro on macOS, Tahoma on Windows, and Noto Naskh Arabic on Android — same CSS, different metrics. MDN’s font-family documentation recommends fallback lists ending in a generic family, not reliance on OS defaults. Agents must detect missing glyphs (a .notdef box or collapsed advance width during measurement) and fall back to coverage-complete Noto families such as Noto Sans Devanagari.
The Lint Table
| Script | Key metric | Minimum threshold | Rationale |
|---|---|---|---|
| Devanagari | line-height |
≥ 1.8 (proposed) | Clears matras/stacked conjuncts (W3C) |
| Arabic | line-height |
≥ 1.6 (proposed) | Tashkeel clearance above/below baseline |
| Arabic | glyph coverage | 100% of codepoints resolve | OS defaults differ (MDN) |
| CJK (zh) | word-break / overflow-wrap |
break-all / break-word |
No spaces; UAX #14 allows inter-ideograph breaks |
| Japanese | line-height |
≥ 1.7 (proposed) | Text-avalanche density convention |
| Korean | font-size, letter-spacing |
≥ 15px (proposed); declared, not inherited | Pop-futurism, dual-ecosystem norms |
Each row is a unit-testable predicate. Lint sketch for rule 1:
const cs = getComputedStyle(el), r = parseFloat(cs.lineHeight) / parseFloat(cs.fontSize);
if (/[\u0900-\u097F]/.test(el.textContent) && r < 1.8) fail("devanagari-leading", el, r);
Closing
Insert a typography lint between generation and render: extract lang and text-node codepoints, apply the table, ship only pages whose scripts pass. This review is based on official documentation, design convention references, and community reports — we did not run the tool hands-on. Agents design better not by acquiring taste, but by converting conventions into signals they can perceive and checks they can enforce.