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.
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.
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"/>
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:
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.
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>
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:
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).
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.
An RTL <table>
element will rearrange and right-justify automatically:
First Column | Second | Third |
First Column | Second | Third |
First Column | Second | Third |
First Column | Second | Third |
First Column | Second | Third |
First Column | Second | Third |
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.
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.
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.
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.
The currency symbol is typically written after (to the left) of the number value.
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.
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:
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 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.
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.
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.
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
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.