مرحبا to the RTL Guide

While reading this page from top-to-bottom, you'll learn how to make websites that work in languages which write from right-to-left.

Which languages do that?

Multiple languages which use Arabic, Hebrew, Syriac, Dhivehi, Adlam, and a few other scripts follow this right-to-left pattern. Most of the people who use these languages are in the Middle East / North African region. But anyone could be writing content or commenting and get flustered by how your website handles their words.

How should a text input work?

Type anything in this box, and we'll convert your typing into Dhivehi script. Notice anything weird about writing right-to-left script in a left-to-right box?

The typing indicator stays on the right, while the written text continues spooling out from the left. It's not impossible to use, but it's weird for the user - similar to typing English in this box:

Here we've made our first improvement - setting <input type="text" dir="rtl"/> when we expect a right-to-left language:

If you don't know what language to expect, there's a simple way to make text input work for everyone - use <input type="text" dir="auto"/>

You can test it out by typing in either language, or pasting RTL words from somewhere on this page.

How do I change the overall layout?

The first step is to set dir="rtl" in the body tag or another high-up parent element on the page. It'll turn <ul>, <ol> and other elements around for you:

  1. Hello
  2. World
  1. Hello
  2. World

It looks a little weird to see this ".1" list formatting in English! But I've seen official signs in RTL languages and this is appearing correctly.

Horizontal Lists

It's common practice to have a list of ordered links, buttons, and/or dividers in your navbar, something like:
<strong>RTL Corp</strong>
<button>(1) Product</button> |
<button>(2) Company</button>

RTL Corp |

Inside a dir="rtl" element, or dir="auto" with RTL text, they switch their order seamlessly, including moving the preceding numbers and punctuation to the right side of the button:

RTL Corp |

So why not use dir="auto" like we saw in input elements?
If I did that, and then started the line with LTR content, then our text will follow LTR layout and mess up the order of the remaining RTL content. The numbers such as (1) are shown as "1)" on the left with an errant ")" on the right. (Both parentheses appear as ) because the characters represent open and close paren, and their direction depends on local context).

RTL Corp |

Will I need to change my CSS?

The answer is... yes, and it's complicated.

An element which you set to float: left should be flipped to float: right, and vice-versa.

This could be a company logo which you have in the top-left, Log In | Sign Up links in the top-right, or a sidebar.

float: left

float: right in RTL



An RTL <table> element will rearrange and right-justify automatically:

First ColumnSecondThird
First ColumnSecondThird
First ColumnSecondThird
First ColumnSecondThird
First ColumnSecondThird
First ColumnSecondThird




But consider this data editor (which uses CSS and not the <table> element) from OpenStreetMap iD. The design includes padding, rounded corners, and CSS triangles to make this appealing to the user. On the bottom right corner of the table, there's a rounded edge that doesn't exist on the bottom left edge, where it meets the 'Add Tag' button.

When we switch to an RTL layout, only the text justification changes automatically.

We need to revamp the style and order of elements and CSS styling, or it will look confusing and wrong. The most priority element needs to be moved to appear on the right. First let's fix any positioning / layout code by switching float: left, changing right offset to a left offset, and negating the original right offset by setting it to right: auto.

[dir='rtl'] .tag-row .key-wrap, [dir='rtl'] .tag-row .input-wrap-position {
    float: right;
}
[dir='rtl'] .tag-row button {
    right: auto;
    left: 10%;
}
[dir='rtl'] .tag-row .tag-reference-button {
    left: 0;
}

If this seems particularly wordy, you could use a CSS pre-processor library and wrap all of your RTL-specific code inside of a [dir='rtl'] { } block.

Now the final step is flipping and negating rules such as border-left, border-left-width, and border-top-left-radius. Another example: combobox-caret can be fixed by negating its margin-left: -30px to 0 and re-applying it as margin-right: -30px.

At no point do we need to change the order or content of our HTML - this is all happening on the CSS level.

There are libraries such as CSS Janus and R2 which flip any CSS properties automatically. You can get R2 as a Ruby gem which will automatically create a separate CSS file. But when you do that, watch out for things which shouldn't change, such as sprites' background-position. You can mark these CSS blocks to keep them from being broken by your helper.

Icons

Arrows (including Undo and Redo icons) should be flipped either by using the opposing icon images, or with a CSS transform. Follow this pattern for any other icon which is conveying moving forward in space or time.

Some icons are open to interpretation: for OpenStreetMap we discussed flipping the geolocation and line drawing icons, but it wasn't clear if there was a known convention for this.

Star Ratings

According to a Unicode discussion, in Hebrew half-stars in star ratings are filled in from right-to-left. Unicode 11 added LTR and RTL half-star characters in 2018.

In Iraqi Kurdistan, I found a Careem sign which indicated star ratings are filled in from left-to-right.

Numbers

In the Arabic numbering systems, the most-significant digit is written on the left, similar to our own system: (100 | Arabic: ١٠٠) - We may call our digits "Arabic numerals", but the Arab world later adopted Indic numerals for many cases.

The Hebrew numbering system is rarely used except for numbering a list or representing dates on the Hebrew calendar. It has no zero, so it works similar to Roman numerals and is written right-to-left (14 | Hebrew: יד‎)

The Adlam numbering system is also right-to-left.

Currency

The currency symbol is typically written after (to the left) of the number value.

  • The currency in multiple countries of the Gulf region is called rial (ريال) and it can also be written with one Unicode character (﷼).
  • The currency in Israel and Palestine is the Israeli New Shekhel, which uses this Unicode character: ₪
  • Other Middle East / North African countries use "dirham" and "dinar" with their own spellings and symbols

Markdown tips

When writing markdown, particularly on GitHub, most pages expect a left-to-right format.

Enclose any RTL text with <div dir="rtl">...</div>. Leave a blank line between the HTML tags and the enclosed content.

Charts

There doesn't appear to be a global consensus on charts. Line charts are almost always left-to-right. Some examples which I've seen on the internet:

  • A World Bank report has a right-to-left horizontal bar chart, while time is represented on left-to-right line charts
  • Al Arabiya video shows a combined bar and line chart with years advancing right-to-left, then financial bars with higher numbers on the right
  • A line chart from a Jordanian e-Learning company, with all Arabic labels and numbers, shows time progressing from left to right. Y-axis labels go up the left side.
  • A scatter plot with the origin in the lower right.
  • A trendline icon from a Lebanese NGO, represents declining financial markets with an arrow pointing down and to the left, indicating time going right to left.
  • A horizontal bar chart from Arabic Wikipedia, with bars right-aligned
  • A bar chart from an Islamic Finance market analysis, with English and Arabic versions, has multiple categories with years side-by-side. The later year is on the left, indicating time progressing from right to left.
  • A bar chart from a Maldivian government commission, with Dhivehi labels and Latin numerals (the preferred numerals in the Maldives), shows two years side-by-side. The later year is on the left, indicating time progressing from right to left. Y-axis labels go up the left side.
  • A line chart in Hebrew shows declining COVID-19 cases in a left-to-right chart.
  • A weather forecast in Dhivehi shows hourly temperatures in a LTR line chart, and the icons/temps for each day of the week below it in RTL order.

Canvas Text

This is a particularly interesting case which you might run into with data visualization or graphics. You can write text on a <canvas> element using this code:

ctx.fillText("hello", 0, 20);
When writing RTL text, the X-coordinate determines the left-most end of the text:
marhaba = "مرحبا";
ctx.fillText(marhaba, 0, 20);

If you are making an RTL layout inside <canvas> and want the text to align with the right border, you will need to calculate the left X-coordinate to place your text. Here's how that works:

/* set text size, font, etc first */
textWidth = ctx.measureText(marhaba).width;
ctx.fillText(marhaba, canvas.width - textWidth, 20);

In these examples, I see a little whitespace to the left of "hello" but the beginning and end of "مرحبا" contact the border of the <canvas>. Consider shifting your Arabic text slightly to the left or right to compensate.

SVG Text

SVG is relatively uncommon, but comes in handy with mapping and data visualization (such as D3). On Chrome / Webkit browsers, there is a known bug with <textPath> elements and RTL text, where the text does not appear in a right-to-left direction and there is no text-shaping connecting the Arabic script. Except for text-shaped languages, you can fix this issue by reversing the string with some additional cautions to keep any vowel signs with their letters. Remember to modify the text only for users in Chrome or Webkit browsers.

The details of how to do text-shaping in client-side JavaScript are rather complicated, but you can try using this library.

JavaScript gotchas

Sometimes in interactive JS, you are expecting the edge of the screen and the elements to be in a particular layout. You should calculate the edge of each element without expecting them to be on the left or right, 0 X-coordinate or max-width X-coordinate.

How should a video player work?

Trick question! Video players and icons go back to how tapes and older players worked, so they have the same conventions in right-to-left languages.

Learn More

Check out the Material Design page on bidirectionality by Google.

Also read "Welcome to online directionality flipping" on RTL.wtf by Wikipedian Moriel Schottlender
and rtlstyling.com by Ahmad Shadeed.

For RTL and other common errors rendering Arabic: IsThatArabic.com

Updating and Expanding this Guide

This guide is available under a Creative Commons Zero license, meaning it has the minimum level of permissions and copyrights in your country. Feel free to copy, edit, and translate it. You can contribute and ask questions on the GitHub repo or sending a Tweet to @mapmeld.