RTL Languages on the Web: Arabic, Hebrew, Persian, Urdu

By the ResilientLang team · Published · 6 min read

To support right-to-left (RTL) languages such as Arabic, Hebrew, Persian and Urdu, set lang and dir="rtl" on the <html> element, write your CSS with logical properties instead of left/right, mirror only the icons whose meaning depends on direction, and test mixed-direction content such as numbers, URLs and brand names. Language declaration does not set direction, so both attributes are needed.

How do you set direction in HTML?

Put the base direction in markup. W3C's guidance for an RTL page is to add dir="rtl" to the html element along with a lang attribute; blocks inherit it, which right-aligns paragraphs, reverses the column order of tables, starts form input at the right and sets the direction for alt and title text. MDN states the same and adds that lang does not imply direction.

<html lang="ar" dir="rtl">

Use dir on a smaller element only when its direction differs from its surroundings, such as an English quotation inside an Arabic paragraph:

<p lang="ar" dir="rtl">
  اقرأ <cite lang="en" dir="ltr">How the Grinch Stole Christmas!</cite> اليوم.
</p>

Why markup rather than CSS? W3C notes that direction information should survive when stylesheets are not applied and can affect meaning, and MDN recommends dir over CSS direction because directionality relates to content, not presentation. CSS direction and unicode-bidi can override dir, so avoid setting them on the same elements in conflicting ways.

Typical language values and directions:

Language BCP 47 tag Script and direction
Arabic ar Arabic script, RTL
Hebrew he Hebrew script, RTL
Persian (Farsi) fa Arabic-based script, RTL
Urdu ur Arabic-based script, RTL

See language and region codes for how to add regions, for example ar-EG.

How do CSS logical properties help?

Logical properties describe layout relative to the flow of text rather than to physical edges. MDN's CSS logical properties module explains that the inline dimension runs parallel to the text flow and the block dimension perpendicular to it, and that properties which once accepted only top, left, right or bottom now also accept flow-relative values such as inline-start and inline-end. The aim, MDN says, is that content translated into languages with different writing modes renders as intended.

/* Physical: needs an RTL override */
.card { margin-left: 1rem; text-align: left; border-left: 3px solid; }

/* Logical: works in LTR and RTL */
.card {
  margin-inline-start: 1rem;
  text-align: start;
  border-inline-start: 3px solid;
  padding-inline: 1rem;
}
.badge { inset-inline-end: 0; }

Practical migration order:

  1. Replace left/right in margins, padding, borders, positions and text-align with -inline-start/-inline-end or start/end.
  2. Use Flexbox and Grid, which follow the writing direction automatically; avoid row-reverse hacks.
  3. Review transform: translateX(), background positions, gradients and animations, which stay physical and need an RTL-aware variant.
  4. Check which browsers you must support in the MDN compatibility tables for each property before relying on them. We did not verify a support statement beyond MDN's property pages.

Which elements should be mirrored?

Mirroring is a design judgement, not a W3C rule. Common practice, consistent with design-system guidance such as Material Design, is:

  • Mirror: layout order (navigation, sidebars, card image/text order), back and forward arrows, breadcrumbs, progress bars, sliders, and icons that imply reading direction.
  • Do not mirror: logos and brand marks, photographs, symmetrical icons, media-playback controls (they represent tape direction, not text direction), clocks, charts' axes where convention is fixed, and phone numbers, email addresses and code, which remain left-to-right.

Have a native reader review the result. Mirroring the wrong icon is a common cause of confusing RTL interfaces.

How does bidirectional text behave?

RTL text is rarely purely RTL. Latin brand names, numbers, URLs and punctuation appear inside it, and the Unicode bidirectional algorithm decides their order. W3C's explanation of the algorithm highlights three practical points:

  • Neutral characters such as spaces and punctuation take the direction of the surrounding text, or the base direction between opposite-direction runs. That is why a trailing exclamation mark can land on the wrong side of an embedded English title unless the phrase is isolated.
  • Digits run left-to-right even inside RTL text without breaking the surrounding RTL run.
  • Embedded passages often need their own dir so that their punctuation falls on the right side.

For user-generated content or database values of unknown direction, use dir="auto", or wrap the value in <bdi>. MDN warns that dir="auto" is a heuristic based on the first strongly directional character, not language detection: a comment starting with an English name and continuing in Arabic will be treated as LTR. When you know the direction, state it.

<li>الطلب <bdi>#A-1024</bdi>: تم الشحن</li>

Which numerals should you display?

Arabic-speaking regions differ: some locales conventionally use Arabic-Indic digits (١٢٣) and others use Western digits (123). MDN's Intl.NumberFormat page shows that new Intl.NumberFormat("ar-EG").format(123456.789) produces Arabic-Indic digits (١٢٣٤٥٦٫٧٨٩), and that the nu Unicode extension key (for example -u-nu-latn) can request a different numbering system. Let the locale choose by default and make it configurable if your audience expects otherwise. Format dates, currencies and phone numbers with the same locale-aware APIs rather than string concatenation.

What about fonts and typography?

  • Pick a font with proper support for the script; Arabic, Persian and Urdu need connecting-letter shaping and may need different styles. Nastaliq-style Urdu typography often needs more line height than Latin text (a general typographic observation, not a standard).
  • Do not apply letter-spacing to connected scripts; it breaks joins.
  • Avoid italics and all-caps transformations, which do not exist in these scripts.
  • Set font-family per :lang() so fallback fonts do not silently pick a poor face.

How should you test an RTL site?

  1. Flip dir in DevTools on an LTR page to spot hard-coded left/right values, then review with real translated text.
  2. Test forms: placeholder alignment, validation messages, input fields for numbers and emails.
  3. Test mixed content: product codes, URLs, dates, prices and brand names inside RTL sentences.
  4. Check the language switcher itself; see our notes on labelling languages in their own script and on accessible markup.
  5. Review with native speakers, since automated checks cannot judge mirroring choices.

Are there SEO considerations for RTL?

Search engines treat RTL sites like any other language version. Google's international guidance asks for separate URLs per language version and reciprocal annotations, and it states that it does not use the HTML lang attribute to detect page language. Direction is therefore a usability and accessibility matter. Apply the usual hreflang rules and make sure titles and descriptions are translated, not just body text.

Key takeaways

  • Set lang and dir="rtl" on <html>; lang does not set direction.
  • Prefer the dir attribute over CSS direction, and use dir="auto" or <bdi> for unknown-direction data.
  • Adopt CSS logical properties and flow-aware layout (Flexbox, Grid) so one stylesheet serves both directions.
  • Mirror direction-dependent icons and layout, but not logos, media controls or phone numbers; verify with native readers.
  • Use locale-aware formatting for numerals, dates and currency, and test mixed LTR and RTL content.

Sources

Frequently asked questions

How do I make a website right-to-left?

Set dir="rtl" and the right lang value on the html element, for example lang="ar" dir="rtl". Then write your CSS with logical properties such as margin-inline-start and text-align: start, so layout flips automatically, and mirror only direction-dependent icons. The lang attribute alone does not change direction.

Should I use the dir attribute or CSS direction?

Use the dir attribute. MDN and W3C both recommend expressing base direction in markup because it describes the content, not its presentation, and still works when CSS fails to load. CSS direction and unicode-bidi can override it but are better kept for cases markup cannot cover.

Do all icons need to be mirrored in RTL layouts?

No. Mirror icons whose meaning depends on direction, such as back arrows and progress indicators. Do not mirror symmetrical icons, logos, or media-playback controls, which show the direction of the tape rather than reading order. Always check with a native reader; this is common design practice rather than a standard.

Does RTL affect SEO?

Direction is not a ranking factor that Google documents. What matters is the same as for any language: separate crawlable URLs, reciprocal hreflang annotations, a correct language code, and genuinely translated content. Get the lang value right, but do not expect dir to influence rankings.

Keep reading