RTL & bidi
How to build layouts that work left-to-right and right-to-left from the same code, and handle mixed-direction text correctly.
Direction comes from the root
Direction and language are set once, on <html>. Components never hard-code a direction; they inherit it.
<html lang="ar" dir="rtl">Both English and Arabic are first-class. Design and review every screen in both, not just the default. Every preview on this site has an EN / AR toggle that switches the example’s language and direction, so you can check both without leaving the page.
Logical properties only
Physical properties (left, right, margin-left…) describe the screen. Logical properties (inline-start, inline-end) describe the reading direction, so the layout mirrors itself. Physical properties are not allowed anywhere in the system.
| Physical (don’t) | Logical CSS | Tailwind |
|---|---|---|
margin-left | margin-inline-start | ms-* |
margin-right | margin-inline-end | me-* |
padding-left / -right | padding-inline-start / -end | ps-* / pe-* |
left: 0 / right: 0 | inset-inline-start / -end | start-0 / end-0 |
text-align: left | text-align: start | text-start |
border-left | border-inline-start | border-s |
border-top-left-radius | border-start-start-radius | rounded-ss-*, rounded-s-* |
float: left | float: inline-start | float-start |
Toggle the preview below between EN and AR. The markup is identical; only dir and lang on the container change, and the layout, alignment and directional icons follow:
Icons
Icons that point along the reading direction flip in RTL; vertical, symmetric and real-world icons don’t. Flip with rtl:-scale-x-100 on the icon. The full list is on Icons › RTL flipping.
| Flip | Don’t flip |
|---|---|
| Horizontal and diagonal arrows, left/right chevrons | Vertical arrows and chevrons, download, upload |
| Send, reply, forward, undo / redo | Symmetric glyphs: plus, ×, check, info, alerts |
| Trending up / down, log in / out, external link | Spinner, refresh, clock (rotation, not direction) |
| Move left / right | Real-world objects (search, document) and brand marks |
<ChevronRight className="size-4 rtl:-scale-x-100" />Numbers, currency and identifiers
Numbers, IBANs, phone numbers, emails and code are left-to-right even inside Arabic text. Isolate them, so the surrounding punctuation doesn’t jump to the wrong side:
- Wrap inline runs in
<bdi>, or give themdir="ltr". Both isolate the run. - Inline
codeon this site is isolated withunicode-bidi: isolateautomatically. - Inputs for Latin-only data (email, IBAN, phone) get
dir="ltr", so the caret and the text move in the expected direction.
<p>
سيتم تحويل <bdi>SAR 12,500.00</bdi> إلى الحساب <bdi dir="ltr">SA03 8000 0000 6080 1016 7519</bdi>
</p>
<input type="email" dir="ltr" autoComplete="email" />Review checklist
- The screen is reviewed in both
dir="ltr"anddir="rtl". - No physical properties or utilities (
left,right,pl-,mr-,text-left…). - Directional icons flip; object icons don’t.
- Amounts, IBANs and phone numbers are isolated and read correctly.
- Truncation and wrapping work in both languages. The Arabic and English versions of a label can differ a lot in length.