4 min read · 2026-10-26
Line height is not a matter of taste
Arabic ascenders and descenders, vocalisation marks, and the clipping that happens when a Latin leading value meets an Arabic face.
The Arabic Layout Requirements say it plainly: Arabic ascenders and descenders extend much further than those of the Latin script, and care must be taken to align text in the two scripts when they appear together. (§7.4)
That sentence is the whole reason a 1.4 line-height that looks generous in Inter looks like a trap in Cairo. The Latin line box is sized for Latin extremes. Arabic adds letters that climb above the ascender — أ, ل with a hamza — and descenders that drop below the baseline for ج, ح, خ, ر, ز, و. Vocalisation marks sit outside both.
What clipping actually looks like
Set a heading in a Naskh face with line-height: 1.2 and
overflow: hidden and the top of a hamza is cut off. Set body text at
1.4 with two lines of fully vocalised text and the fatha of one line sits
inside the line box of the one above it.
This is why the type-scale tool sets a floor of 1.75 for Arabic rather than scaling the Latin leading. It is not a magic number: it is the point where the faces tested here stop colliding, and it is a starting point.
The test that finds it
Use a string with the extremes in it, at the smallest size you ship, and measure. Not the eyeball test on one word — the actual bounding boxes.
<p lang="ar" dir="rtl">أَجِدُّ يَجِدُّ وَجْهُ الْحَقِّ</p>
Then compare the range's rect against the parent's:
const range = document.createRange();
range.selectNodeContents(paragraph);
const text = range.getBoundingClientRect();
const box = paragraph.getBoundingClientRect();
const clipped = text.top < box.top || text.bottom > box.bottom;
If clipped is true, the leading is too tight or an ancestor is hiding the
overflow. Both are bugs; neither shows up in a Latin screenshot.
The dotted circle
When a font has no glyph for an isolated mark, browsers draw it against a dotted circle placeholder. Seeing one on a live page means a font is missing a mark the copy uses, usually because the subset dropped it. The fix is in the subset, not in the CSS.
What to set
- A separate leading value per script, not one shared value.
- No
overflow: hiddenon headings that contain Arabic. - Vocalisation marks kept in the subset if any content can contain them.
- Re-check after a font change: the same 1.75 is generous in one face and tight in another.
The type scale emits both leading curves from one base size, with the Arabic floor applied and the Latin curve left alone.
Sources
- W3C Arabic Layout Requirements §7.4 — baselines and line height.
- W3C Arabic Layout Requirements §7.3 — why stretching Arabic is not letter-spacing.
- MDN: Range.getBoundingClientRect