rtl-ui
ساخت و بازبینی رابطهای RTL بدون بههمریختگی متن، اعداد، فرمها و انیمیشنها.
این مهارت برای ساخت و ریویوی رابطهای راستبهچپ فارسی، عربی، عبری و اردو طراحی شده است. از تنظیم درست lang و dir تا استفاده از CSS منطقی، چیدمان Flex/Grid، جهت آیکنها و رفتار متنهای ترکیبی را پوشش میدهد.
همچنین خطاهای رایج در شماره تلفن، ایمیل، URL، اعداد، منوهای خارج از صفحه، transformها، فونتها و ارتفاع متن را بررسی میکند. checker بدون وابستگی آن به پیدا کردن خطاهای RTL پیش از انتشار کمک میکند.
چه چیزی میگیرید
- تنظیم صحیح `dir` و `lang` از نخستین رندر صفحه
- تبدیل propertyها و کلاسهای فیزیکی به CSS و Tailwind منطقی
- مدیریت درست متنهای ترکیبی، شماره تلفن، ایمیل، URL و اعداد با `bdi` و isolate
- بررسی منوهای کشویی، آیکنهای جهتدار، transformها و اسکرول افقی در RTL
- اجرای checker بدون وابستگی برای یافتن خطاهای رایج در فایلهای پروژه
برای چه کاری خوب است
- توسعهدهندگان وبی که صفحههای فارسی، عربی، عبری یا اردو میسازند
- تیمهایی که یک UI موجود را از LTR به RTL تبدیل میکنند
- پروژههایی که منوی کشویی، فرم، دادههای عددی یا انیمیشن دارند
- ریویوی نهایی رابط پیش از انتشار و تست در عرضهای 360 و 768 پیکسل
برای چه کاری نیست
- صفحههایی که فقط برای زبانهای LTR طراحی شدهاند
- حل مشکلات ترجمه، نگارش یا انتخاب فونت بدون وجود مسئله در پیادهسازی RTL
- تغییرات گرافیکی یا طراحی بصری که ارتباطی با جهت رابط ندارند
دربارهٔ این اسکیل
RTL UI
Right-to-left bugs are invisible in an English review and obvious to every
Hebrew or Arabic user. Almost all of them come from a handful of habits:
writing left/right where the layout should follow the reading direction,
and letting numbers, phone numbers and Latin words fend for themselves inside
RTL sentences. Follow the rules below while you write the code, then run the
checker before you call the work done.
The five rules
- Direction lives in HTML, set before the first paint. Put
<html lang="he" dir="rtl">(orar,fa,ur) in the static HTML or the root layout. If the language is picked at runtime, setlanganddiron<html>in an inline script in<head>, before the stylesheet renders. Never use the CSSdirectionproperty for page direction: thedirattribute is what browsers, screen readers and Tailwind'srtl:variant read. - Only logical CSS. Never
left/rightfor layout. Usemargin-inline-start/end,padding-inline-start/end,border-inline-start/end,border-start-start-radius(and the other three corners),inset-inline-start/end,text-align: start/end,float: inline-start/end. In Tailwind (3.3+), use the table below. - Let flex and grid follow
dir. A flex row and grid columns already run right-to-left in an RTL page. Never addflex-row-reverse/row-reverse"for RTL": it flips the row a second time, back to LTR order. - Isolate mixed-direction text. Numbers, prices, phone numbers, e-mails, URLs, product codes and Latin names inside an RTL sentence get reordered by the Unicode bidi algorithm. Wrap values of unknown direction in
<bdi>(orunicode-bidi: isolate), give user-generated textdir="auto", and givetype="tel",type="email"andtype="url"inputsdir="ltr". - Respect the script. No
letter-spacingon Arabic, Persian or Urdu: it pulls joined letters apart (scope tracking to Latin with:lang(en)). Arabic needs more line-height than Latin (about 1.6-1.8 for body text) or its dots and marks clip. Form controls do not inherit the page font: addbutton, input, select, textarea { font: inherit; }.
Tailwind: physical class -> logical class
| Physical (does not flip) | Logical (flips with dir) |
|---|---|
ml-* mr-* pl-* pr-* | ms-* me-* ps-* pe-* |
left-* right-* | start-* end-* |
text-left text-right | text-start text-end |
rounded-l-* rounded-r-* | rounded-s-* rounded-e-* |
rounded-tl-* rounded-tr-* rounded-bl-* rounded-br-* | rounded-ss-* rounded-se-* rounded-es-* rounded-ee-* |
border-l-* border-r-* | border-s-* border-e-* |
scroll-ml-* scroll-pr-* ... | scroll-ms-* scroll-pe-* ... |
float-left float-right | float-start float-end (v4), or use flex/grid |
space-x-* (physical up to v3) | gap-x-* on the flex/grid parent |
Use rtl: / ltr: variants only for things that are truly different per
direction (an icon that must be mirrored, a transform). They only work whendir is on an ancestor before the first paint (rule 1).
Traps that pass review and break in production
Each of these shipped in a real product before it was caught.
- Direction flash. The static HTML says
lang="en"(or nothing) and a script switches to RTL after load: every first visit renders left-to-right, then jumps. The staticlang/dirmust match the default language. rtl:classes that silently do nothing. Whendiris applied late or on the wrong element, everyrtl:variant misses. In one app a drawer styled only withrtl:classes disappeared completely in Hebrew.- Off-canvas menus create a horizontal scrollbar in RTL. A drawer parked off-screen with
left: 0; transform: translateX(-100%)is unreachable in LTR but becomes scrollable overflow in RTL, because RTL pages scroll toward the left. Position it withinset-inline-start, mirror the transform under[dir="rtl"], and useoverflow-x: clip(nothidden, which breaksposition: stickybelow it). - Transforms are physical.
translateX, slide-in animations andscaleXdo not flip. Mirror them under[dir="rtl"]. - Directional icons. Back/next arrows, chevrons in navigation, and "continue" arrows must be mirrored in RTL (
rtl:-scale-x-100). Do not mirror logos, check marks, clocks, or media play/pause controls. - Centring is not a direction bug.
left: 50%+translateX(-50%)(orleft-1/2 -translate-x-1/2) centres in both directions. Changing only the first half tostart-1/2pushes the element off centre in RTL. - Phone numbers and times turn around. Inside RTL text,
+972 4 000 0000renders as0000 000 4 972+and09:00 - 18:00as18:00 - 09:00: the spaces between the number groups take the RTL direction, so the groups are laid out right to left. Wrap such values in<bdi dir="ltr">or an LTR isolate. In plain-text channels (SMS, WhatsApp, push, e-mail subjects) there is no markup: use Unicode isolates or marks (LRI U+2066 ... PDI U+2069, or LRM U+200E / RLM U+200F). - A Hebrew line that starts with a Latin word goes LTR. "WhatsApp ..." at the start of a Hebrew paragraph makes
dir="auto", and every plain-text app that guesses direction from the first strong letter, lay the whole line out left-to-right. Set the direction explicitly, or prefix plain text with RLM. - Digits.
toLocaleString('ar')may return Arabic-Indic digits (U+0660-0669) depending on runtime and region. Decide which digits the product shows and pin it:'ar-u-nu-latn'for 0-9,'ar-u-nu-arab'for Arabic-Indic. Never mix the two on one screen. - SVG and charts do not mirror themselves. Setting
direction="rtl"on an SVG root changes whattext-anchor="start"means and moves every label. Keep the SVG geometry LTR and give each RTL string its own direction. - Fonts fall back silently. A web font blocked by CSP or the network falls back without an error, often to a font with poor Hebrew/Arabic glyphs. Start the stack with
system-uiand self-host the web font. - Fixed heights clip translated text. Hebrew, Arabic and Russian strings are often longer, and Arabic is taller. Use
min-height, neverheight, on text containers, and check the longest language at 360px wide. - Uppercase and tracking are Latin tools.
text-transform: uppercasedoes nothing to Hebrew/Arabic, so a design that relies on it for emphasis loses it; use weight instead.
Verify before you finish
- Run the checker on what you changed:
python "<this skill's directory>/scripts/rtl_check.py" src/(it printsfile:line:col severity rule message -> fix). Fix every error. Read every warning; if a line is right on purpose, end it with the commentrtl-check: ignore.--strictalso lists transforms and directional icons to review by eye. - In the browser: switch the language live (not only on first load) and confirm the header, drawer, forms and icons follow; check 360px and 768px widths with the longest language; look for a horizontal scrollbar; type a phone number and an e-mail into the forms.