Right to Left Rendering
In a right-to-left, top-to-bottom script (commonly abbreviated RTL), writing starts from the right of the page and continues to the left. This can be contrasted against left-to-right writing systems, where writing starts from the left of the page and continues to the right.
Arabic, Hebrew, Persian, and Urdu Sindhi are the most widespread RTL writing systems in modern times.
How RTL works in HTML
You can control the direction of text in the rendered HTML using the
dirltr<div>  <div dir="rtl">I'm right to left مرحباً بالعالم</div>  <div dir="ltr">I'm left to right مرحباً بالعالم</div></div>Looking at the English sentence, it will appear as if it's simply right aligned. But the directional flow of the content has actually changed. This becomes more evident with a table element.
<table border="1">  <tbody>    <tr>      <td>First Cell</td>      <td>Second Cell</td>    </tr>  </tbody></table><table border="1" dir="rtl">  <tbody>    <tr>      <td>First Cell</td>      <td>Second Cell</td>    </tr>  </tbody></table>Setting direction for an entire page
If you're building an entire page in an RTL language you'll most likely want to set the 
 attribute only once, on a top level dir
.<div>
In contrast, setting
dir<body><html><body>  <div dir="rtl">My page goes in here!</div></body>Dealing with unknown direction like user input
Sometimes you don't know beforehand what direction you want to render. HTML5 added an auto value(new tab) to the
dirBeware: Some input values, like an e-mail address will still be expected to be written left-to-right, even if the language spoken is right-to-left.
Dealing with numbers
Here's another edge case: Although Arabic text is written right-to-left, numbers are written the same way as in left-to-right languages(new tab). So the number 321 (three hundred and twenty one) is written ٣٢١ ("321", not "123").
Take care if you format numbers and insert spacing, like in a phone number. As shown here:
<div dir="ltr">Phone: 0703 123 456 789</div><div dir="rtl">0703 123 456 789 مرحباً بالعالم</div><div dir="rtl"><span dir="ltr">0703 123 456 789</span> مرحباً بالعالم</div><div dir="rtl">مرحباً بالعالم <span dir="ltr">0703 123 456 789</span></div>Notice how one of the phone numbers have been scrambled? A
<span dir="ltr">How RTL works in CSS
Dealing with direction in HTML was fairly trivial. Now, how do we make sure our CSS layouts are bi-directional. Unfortunately, it gets a little trickier.
To illustrate, let's say I want to apply a margin after an element, like the following:
<div style={{ display: 'flex', background: 'pink' }}>  <div style={{ marginRight: '10px', background: 'aqua' }}>Box 1</div>  <div style={{ background: 'red' }}>Box 2</div></div>Ok, looks good. Now if we change the direction of the HTML element:
<div dir="rtl" style={{ display: 'flex', background: 'pink' }}>  <div style={{ marginRight: '10px', background: 'aqua' }}>Box 1</div>  <div style={{ background: 'red' }}>Box 2</div></div>Oh no! The margin is no longer "after" the element, but before. This is because values like left and right become ambiguous in a bi-directional context.
How to write CSS in a bi-directional world?
So how do we fix this? There are essentially two solutions to the problem:
- Replacing/overwriting everything that is "left" to be "right"
- Using CSS Logical Properties
Let's take a closer look:
1. Replacing left with right and vice versa
It may seem like a joke, but the easiest way to deal with this is simply by swapping all directional values with each other. Change
margin-rightmargin-leftdiv[dir=rtl]Replacing all directional CSS properties manually will make you want to quit your job sooner than later. The good news is that some clever people have figured out that this process can be completely automated. There are a range of tools, including a PostCSS RTL Plugin(new tab), that will do this job for you. This will allow you to create one LTR and one RTL CSS file. This works surprisingly well.
2. Using CSS Logical Properties
In the past, CSS has tied itself to physical dimensions and directions(new tab), physically mapping the placement of elements to the left, right and top and bottom.
CSS Logical Properties, do not. You could theoretically replace all non-logical values(new tab) with logical ones in your CSS, and it should then work in a bi-directional context without any further modification.
Instead of
margin-rightmargin-inline-end<div dir="rtl" style={{ display: 'flex', background: 'pink' }}>  <div style={{ marginInlineEnd: '10px', background: 'aqua' }}>Box 1</div>  <div style={{ background: 'red' }}>Box 2</div></div>The main drawbacks (as of now) with CSS Logical Properties is lacking browser support(new tab), and that you would have to forbid any use of non-logical properties like
leftHow RTL works in Fela
In Fela, we can use both solutions with different plugins:
- The "PostCSS replacement strategy" can be achieved with fela-plugin-rtl(new tab)
- Logical Properties support comes with fela-plugin-bidi(new tab)
The later replaces logical properties with widely supported properties such as
margin-rightTo render your page in RTL you have to do two things.
- Set 
 to the top level surrounding HTML elementdir=rtl
- Configure the direction to RTL in a theme and pass it to a <ThemeProvider>
Here's a contrived example on how this is achieved:
<ThemeProvider  theme={{ direction: isRtl ? "rtl" : "ltr" }}}>  <div dir={isRtl ? "rtl" : "ltr">    <App />  </div></ThemeProvider>Only want to render part of a page in RTL? No problem. You can use multiple theme providers, and even nest them.
Recommended Reading
Want to dive deeper into RTL, here are some external articles that dive deeper into the subject:
- User Interfaces For Right-To-Left Languages(new tab)
- Structural markup and right-to-left text in HTML(new tab)
- Understanding Logical Properties And Values(new tab)