RTL Language Support in Website Markup
RTL (Right-to-Left) supports languages written from right to left: Arabic, Hebrew, Persian (Farsi), Urdu. RTL markup is not simply direction: rtl — it's a systemic refactoring of all directional CSS properties and UI components.
Basic RTL Setup
<html dir="rtl" lang="ar">
/* Global reset for RTL */
[dir="rtl"] {
direction: rtl;
unicode-bidi: embed;
}
CSS Logical Properties
Instead of physical properties (left, right, margin-left), use logical properties that automatically adapt to dir:
| Physical | Logical |
|---|---|
margin-left |
margin-inline-start |
margin-right |
margin-inline-end |
padding-left |
padding-inline-start |
border-left |
border-inline-start |
left: 0 |
inset-inline-start: 0 |
text-align: left |
text-align: start |
float: left |
float: inline-start |
Example: back button with arrow — in LTR the arrow is ←, in RTL the arrow is →. With logical properties this is handled automatically:
.back-arrow {
margin-inline-end: 8px; /* in LTR: margin-right, in RTL: margin-left */
/* icon flips via transform or icon direction */
}
Icons and Images
Icons with directional meaning (arrows, back/forward buttons) should be mirrored for RTL:
[dir="rtl"] .directional-icon {
transform: scaleX(-1);
}
Icons without direction (heart, star, checkmark) should NOT be mirrored. Icons with text (logos) should NOT be mirrored.
Flexbox and Grid in RTL
flex-direction: row in RTL automatically reverses. However, explicit margin-left/margin-right won't change — they must be replaced with logical properties.
/* Incorrect: */
.nav-item + .nav-item { margin-left: 16px; }
/* Correct: */
.nav-item + .nav-item { margin-inline-start: 16px; }
Fonts for RTL Languages
Arabic text requires special fonts: Noto Sans Arabic, Tajawal, Cairo, IBM Plex Sans Arabic. Numbers in Arabic context can display as Eastern Arabic numerals (٠١٢٣٤٥٦٧٨٩) or Western numerals — depends on locale.
Bidirectional Text (BiDi)
A page can contain both directions (Arabic + English). CSS property unicode-bidi: isolate isolates blocks:
.ltr-content {
direction: ltr;
unicode-bidi: isolate;
}
For inline elements with opposite direction — use <bdi> tag.
RTL Testing
Quick check tool: Chrome DevTools → Elements → add dir="rtl" to <html>. Or use RTL Toggler extension.
Playwright test:
test('RTL layout', async ({ page }) => {
await page.goto('/ar');
await expect(page.locator('html')).toHaveAttribute('dir', 'rtl');
// Check positioning of key elements
});
Timeline
Adding RTL support to existing LTR site: 2–5 days (depends on physical CSS property usage). Developing with RTL from scratch using logical properties: no additional time with proper practices.







