Design sample Invented freight company, invented shipments. The Kurdish and Arabic here are ordinary interface labels, not marketing copy. Read the design notes →

One interface. Three languages. One stylesheet.

Kurdish and Arabic read right to left. English does not. Most “RTL support” is direction: rtl and a hope — which gets the boxes roughly right and everything inside them subtly wrong. Press a language and watch what moves, and more importantly what deliberately does not.

lang en dir ltr locale en-GB formatted digits

R Rojhelat Freight HM

Shipments this week

The layout CSS, in full

/* what most people write — needs a whole second stylesheet */
margin-left: 1rem;
border-left: 3px solid;
text-align: left;
padding-right: .8rem;

/* what this page writes — mirrors itself, no overrides */
margin-inline-start: 1rem;
border-inline-start: 3px solid;
text-align: start;
padding-inline-end: .8rem;

There is no [dir="rtl"] layout rule anywhere in this sample’s stylesheet. The mirror is a property of the writing mode, not a second design.

What flips, and what must not

  • Layout, padding, borders. Automatic, because they are written logically.
  • The “onwards” chevron. It means a direction, so it mirrors.
  • The progress bar. It fills from the start edge — the right-hand side in Kurdish.
  • The logo. A mark is a picture of itself. Mirroring it produces a different logo.
  • Numbers and money. Digits run left to right in every one of these languages.
  • The reference code. RF-2291 is isolated, or bidi moves the hyphen.
  • A clock or a play button. Time does not run backwards because the text does.

How it is designed

I build for a market where Kurdish, Arabic and English all turn up in the same product, often on the same screen. That is a specific skill, and it is almost never shown in a portfolio — so here it is, working.

direction: rtl is about five per cent of the job

It gets the boxes roughly right and leaves everything inside them subtly wrong. The other ninety-five per cent is writing the layout in logical properties in the first place, then deciding, one by one, which things are directional and which are objects.

Write it logically once, rather than mirroring it twice

margin-inline-start instead of margin-left, border-inline-end instead of border-right, text-align: start instead of left. The panel above is one set of rules producing both directions. The alternative — a base stylesheet plus an RTL override file — means every future change has to be made twice, and the second one gets forgotten.

Not everything should mirror, and the list is short

The logo does not: a mark is a picture of itself, and flipping it makes a different mark. Media controls do not, because play still means forwards. Clocks do not. But the chevron that means onwards does, and the progress bar fills from the right in Kurdish. Getting the bar backwards is the single most common tell that a site was translated rather than designed.

Numbers are the part that quietly breaks

Digits run left to right in all three of these languages, so a price or a reference dropped into an RTL sentence has to be isolated — with <bdi> or unicode-bidi: isolate — or the bidi algorithm reorders the surrounding punctuation and RF-2291 comes out as something else entirely.

Kurdish has no Intl data, and it fails silently

This one caught me while building the page, which is why it is here. Ask any current browser for ckb-IQ and you do not get an error — you get en-US. A fully Kurdish screen then renders Aug 29 and Latin digits, and nothing anywhere reports a problem until a user does.

supportedLocalesOf is the only way to find out, and it has to be asked rather than assumed. This page asks, and falls back to ar-IQ — same script, same region, same digit conventions, which is a far better wrong answer than English. Switch to Kurdish and the header says so out loud rather than hiding it.

Digits are a product decision, not a technical one

ar-IQ resolves to the arab numbering system, so Intl returns Eastern Arabic-Indic digits by default. Whether that is what a particular audience wants is a question for the client, not for the library — plenty of Iraqi software uses Western digits throughout. Either can be forced with a locale extension (ar-IQ-u-nu-latn), and the header above prints both so the difference is visible rather than argued about.

The font stack has to cover the script

A Latin-only stack falls back to whatever the system has, and Kurdish renders in a substitute face with the wrong metrics and broken joining. That single omission is why so much bilingual work looks unfinished even when the layout is correct.

Other demos · Hire the developer