RTL support
1) Principles
1. RTL is not a translation of text, but a mirroring of thinking. Axes, reading order, focus order, gestures and navigation change.
2. Logical CSS properties instead of left/right. Go to 'margin-inline-start', 'inset-inline-end', 'border-start-start-radius', etc.
3. Globally turn on the direction, locally isolate LTR fragments. Numbers, URLs, codes, e-mail and IBAN are always read from left to right.
4. Mirror what depends on direction, not meaning. "Play," "↗," "↙" and clock/process icons may not mirror.
5. Test pseudo-RTL. Include 'dir = "rtl "'/' direction: rtl'and pseudo translations before exiting.
2) Direction: 'dir' and boolean properties
Globally on document/root:html
<html lang="ar" dir="rtl"> … </html>
Boolean properties (left/right replacement):
css
.card { padding-inline: 16px; margin-inline: 12px; }
.sidebar { inset-inline-start: 0; }
.button { border-start-start-radius: 12px; border-end-end-radius: 12px; }
Direction selectors:
css
:root:dir(rtl). breadcrumb { flex-direction: row-reverse; }
:root:dir(ltr). breadcrumb { flex-direction: row; }
Local auto-focus of user content:
html
<p dir="auto">…</p>
3) BiDi and mixed text isolation
Mixing Arabic/Hebrew with Latin/numbers breaks the character order. Use BiDi isolation:- Tags: '' (isolates direction), '' (forces override).
- '\u2066 'LRI/'\u2067' RLI - start of LTR/RTL isolation, '\u2069 'PDI - end,
- '\u200E 'LRM/'\u200F' RLM - single-byte tokens for short inserts.
html
<span dir="rtl">
سحب <bdi dir="ltr">IBAN AE070331234567890123456</bdi> بمبلغ
<bdi dir="ltr">2,000. 00 UAH</bdi>
</span>
4) Navigation, hierarchy and layouts
Breadcrumbs: mirror order: "الصفحة الرئيسية‹ الرهان "التأكيد".
Panels/menus: main navbar - on the right; "back" points to the left (to the beginning of the RTL line).
Cards/lists: align headers to inline-start; status icons - to inline-end.
Carousels and swipes: scrolling towards inline-start (in RTL - to the right). Page indicators are also mirrored.
Pagination: the arrow "next" goes to inline-start, "previous" - to inline-end.
5) Icons and images
Mirror directional icons: arrows, "forward/backward," playhead, "expand/collapse."
Do not mirror: icons of text, graphs, hours (if there is a real time arrow), brand logos.
Technically:css
.rtl-mirror { transform: scaleX(-1); transform-origin: center; }
html:dir(rtl). icon--arrow { transform: scaleX(-1); }
For SVG: use 'transform-box: view-box;' to avoid "floating."
Avoid text inside images → localize in separate layers.
6) Forms and input
Content alignment: text-align: start; 'text fields, numeric/amounts/URL/e-mail - LTR.
Attributes:html
<input type="email" dir="ltr" inputmode="email" autocomplete="email">
<input type="number" dir="ltr" inputmode="numeric" pattern="[0-9]">
<input type="tel" dir="ltr" inputmode="tel" autocomplete="tel">
Placeholder/label are localized, but caret in numbers/codes must go from left to right.
Masks: do not "intercept" caret harshly; support insertion and selection.
List/radio/checkbox: signatures to the right of the controls, click areas ≥ 44 × 44 px.
min→max sliders: in RTL, at least on the right edge, at most on the left (or show a scale without inversion and LTR numbers).
7) Numbers, dates, currencies
By default, Arabic locales use Arabic-Indo-spheres (٠١٢٣٤٥٦٧٨٩). Solution - Business Policy:- In financial UI, Latin numbers (0-9) are more often shown for the sake of interoperability, but the format (spaces/signs) is locale.
js new Intl. NumberFormat('ar', { style:'currency', currency:'AED' }). format(2000);
new Intl. DateTimeFormat('he-IL', { dateStyle:'medium', timeStyle:'short' }). format(new Date());
Relative time ('Intl. RelativeTimeFormat '), directional delimiters, and local day/month abbreviations.
8) Typography and readability
Fonts with good Arabic/Hebrew grapheme and ligatures (Arabic shaping).
Line spacing 1. 4–1. 6; avoid narrow tracking.
For Arabic, kashida (lengthening strokes) is allowed when aligning in width - turn on carefully ('text-justify: inter-word; '/engine support).
Prohibit Latin italics inside the Arabic line (spoils the vertical rhythm).
9) Graphs, scales and tables
The X-axes go from right to left; the legend is aligned with the inline-end.
Table columns: "primary" column (name/game) - right; numbers/amounts can remain LTR and be aligned to inline-end.
html
<bdi dir="ltr">+12. 5%</bdi>
10) A11y and screen readers
Make sure 'lang = "ar "'/' lang =" he" 'is exposed: the TTS engine will choose the correct voice acting.
Sound dynamic changes in direction carefully - do not switch 'dir' on fragments unnecessarily.
Live updates ('aria-live = "polite"') - text without mixing directions.
Icons do not convey meaning without text labels; use 'aria-label'.
11) The specifics of iGaming
11. 1 Bet coupon (betslip)
Field order: amount → ratio → potential gain; right signatures, LTR numbers/factors.
Update the coefficients gently; up/down arrows do not need to be mirrored (the meaning of the price direction is universal).
11. 2 Matches/Markets
Align the list of leagues/events with inline-start (in RTL - on the right).
Timers and count - LTR'dir = "ltr" 'with table digits (' font-variant-numeric: tabular-nums; ').
11. 3 Payments/ACC
The IBAN/BIC/phone fields are always LTR.
Bank names/address - RTL.
Errors/validators show markers on the right.
11. 4 Tournaments/leaderboards
Columns: position, nickname, glasses - position on the right; align the glasses to the inline-end (LTR digits).
12) Manufacturing and testing
Pseudo-RTL in maiden:css html. debug-rtl { direction: rtl; }
Auto mirror icons in RTL (directional only):
css html:dir(rtl). icon-dir { transform: scaleX(-1); }
Autotests (example of ideas):
- Layout snapshots at 'dir = rtl'.
- Checks if 'left/right' is missing in the CSS (lint).
- E2E: tabbing order, carousel swipes, slider behavior.
- Visual tests with Arabic text + LTR inserts (e-mail, sum).
13) Design system tokens (example)
json
{
"direction": {
"supported": ["ltr", "rtl"],
"rtlLocales": ["ar", "he", "fa", "ur"]
},
"layout": {
"gap": { "sm": 8, "md": 12, "lg": 16 },
"useLogicalProps": true
},
"icons": {
"autoMirror": true,
"exclude": ["logo", "chart", "clock", "play"]
},
"forms": {
"numericDir": "ltr",
"minTap": 44
},
"a11y": { "contrastAA": true, "live": "polite" }
}
14) Snippets
To switch the direction in the application (React):tsx import { useEffect } from "react";
export function useDirection(locale: string) {
useEffect(() => {
const lang = locale. split("-")[0];
const isRTL = ["ar", "he", "fa", "ur"].includes(lang);
const html = document. documentElement;
html. setAttribute("dir", isRTL? "rtl": "ltr");
html. setAttribute("lang", locale);
}, [locale]);
}
List/breadcrumb harmonization:
css
.breadcrumb { display:flex; gap:8px; }
html:dir(rtl). breadcrumb { flex-direction: row-reverse; }
.breadcrumb__sep { transform: scaleX(var(--dir,1)); }
html:dir(rtl). breadcrumb__sep { --dir: -1; }
Numbers and sums as LTR fragments:
html
<span>الربح المحتمل: <bdi dir="ltr">2,000. 00 UAH</bdi></span>
min→max slider for RTL:
css html:dir(rtl) input[type="range"] { direction: rtl; }
15) Antipatterns
Hard 'left/right' in → styles breaks RTL.
Entering numbers/IBAN/URL without 'dir = "ltr"' → "broken" caret and order.
Mirroring logos/charts/hours.
The same set of icons always mirrors - without exception in meaning.
Carousels, leaflets and paginations are not upside down.
Mixed strings without BiDi isolation → "dancing" characters.
16) Metrics
RTL coverage: the proportion of screens that have undergone an RTL review.
BiDi defects/release: number of mixed text bugs.
Lead time (LTR vs RTL): must not differ> 5-10%.
Input error in number forms - percentage of events with incorrect caret/mask.
CLS/perf: no layout jumps when 'dir' switches.
17) QA checklist
Direction and layout
- '' for RTL locales; ': dir (rtl)' styles are applied.
- Boolean properties instead of'left/right '.
- Navigation / bredkramby / carousels / pagination zerkalitsya correctly.
Text and BiDi
- Numbers/currencies/URL/e-mail - 'dir = "ltr"' or ''.
- No "inverted" characters in mixed strings.
- Localized dates/currencies via'Intl. '.
Forms
- Right labels; click areas ≥ 44 × 44 px.
- Phone/IBAN/amount - LTR caret, correct masks.
- Sliders/lows/highs behave as expected.
Icons/Images
- Only directional are mirrored; exceptions are met.
- No text in pictures without local versions.
А11у/Performance
- 'lang' exposed; SR reads correctly.
- No unnecessary redraws when changing 'dir'.
- Contrast/focus rings correspond to AA.
18) Documentation in the design system
Direction & BiDi section: mirroring policy, list of exceptions for icons.
A set of RTL tokens and a style linter ('left/right' prohibition).
Do/Don't Gallery: carousels, bredcrambs, number forms, sliders, graphs.
Pseudo-RTL scripts and review checklists.
Brief Summary
Proper RTL support is logical CSS properties, conscious mirroring, and strict BiDi isolation. Isolate numbers/URLs in LTR, mirror navigation and directional icons, keep shapes predictable and graphs readable. So the interface for Arabic, Hebrew, Farsi or Urdu will be natural and fast - from a bet coupon and payment forms to tournament tables and live matches.