Building Arabic–English Interfaces That Aren't an Afterthought
Right-to-left support fails when it is bolted on at the end. Treating direction as a property of the layout system from the first commit costs almost nothing and prevents a long tail of defects.
The failure mode
A team builds in English, ships, then adds Arabic. Someone writes a stylesheet that mirrors things with direction: rtl and a pile of overrides. It mostly works — until icons point the wrong way, a phone number renders reversed, a dropdown opens off-screen, and each fix creates two more.
The cause is architectural: layout was expressed in physical terms (left, right) when it should have been expressed in logical terms (start, end).
Use logical properties
Modern CSS provides direction-aware equivalents for nearly every physical property:
| Physical | Logical |
|---|---|
margin-left |
margin-inline-start |
padding-right |
padding-inline-end |
left / right |
inset-inline-start / inset-inline-end |
text-align: left |
text-align: start |
border-left |
border-inline-start |
Set dir once on <html> and correct layout follows automatically. Tailwind exposes these as ms-, me-, ps-, pe-, start- and end-.
The discipline is simple: if a value would need mirroring in the other direction, it must be logical. Reserve physical properties for the few things that genuinely do not mirror.
What does not mirror
Blanket mirroring is its own bug. These stay as they are:
- Logos and brand marks
- Media controls — play still points right, because it follows the timeline rather than the text
- Clock faces, musical notation and mathematical formulae
- Charts with a time axis, which conventionally run left to right even in RTL locales
- Latin-script content embedded within Arabic text
Directional icons — arrows, chevrons, next and back, undo and redo — do mirror.
Bidirectional text
Mixing scripts is where the subtle bugs live. The Unicode Bidirectional Algorithm handles most cases, but neutral characters between scripts inherit direction from context, which produces surprises with punctuation, parentheses and phone numbers.
Practical rules:
- Wrap embedded opposite-direction runs in an element with an explicit
dir, or use<bdi>for user-generated content of unknown direction - Use directional isolates rather than reordering strings manually
- Never build a sentence by concatenating translated fragments. Grammar and word order differ between the languages; use full interpolated strings with named placeholders instead
Numbers, dates and sorting
- Arabic locales may use Arabic-Indic digits (٠١٢٣) or Western digits depending on region and context. Decide deliberately and apply consistently through
Intl.NumberFormat. - Dates may follow Gregorian or Hijri calendars.
Intl.DateTimeFormatsupports both — choose per audience, and consider showing both where the distinction matters. - Sorting differs by locale. Always use
Intl.Collator, never a raw string comparison.
Typography
Arabic is cursive and letters connect contextually. The consequences are practical:
- Line height needs more room. Arabic generally requires greater leading than Latin at the same nominal size.
- Optical size differs. Arabic often needs a slightly larger point size to match the perceived weight of Latin text alongside it.
- Letter-spacing breaks it. Applying tracking to Arabic severs the connections between letters. Never apply it.
- Verify weight coverage. Not every Arabic face includes the full range of weights a design assumes.
Testing
Add both locales to the review process from the beginning. Every layout change gets checked in both directions, and every screenshot test runs twice.
Catching a mirroring bug in review costs minutes. Catching it after launch costs a release — and the bugs arrive in a long, demoralising tail rather than all at once.
References
W3C Internationalization — Structural markup and right-to-left text; MDN, CSS Logical Properties and Values; Unicode Standard Annex #9, Unicode Bidirectional Algorithm.
