I first came across a right to left layout when I was Googling something on the Dubai airport WiFi a few years ago.

Photo of Google in Arabic
Google in Arabic

As a Sinhala and English speaker, I was really surprised. It was hard for me to imagine a language that was read in different direction. But a significant portion of the world uses languages that are read from right to left such as

A world map showing the different written directions of the world
Source: https://en.wikipedia.org/wiki/File:Writing_directions_of_the_world.svg

Recently, I came across RTL layouts again in two of the projects I was working on. Through them, I learnt about how these layouts are actually implemented on the web.

Handwritten text saying Start here aligned to the right

The tricky thing about RTL layouts

What makes RTL layouts tricky is that they completely mirror their left to right (LTR) counterparts.

For example, here is an Airbnb listing in English.

Photo of an Airbnb listing in English
Airbnb listing - Overview

Photo of an Airbnb listing reviews in English
Airbnb listing - Reviews

and here is the same Airbnb listing in Arabic.

Photo of an Airbnb listing in Arabic
Airbnb listing - Overview

Photo of an Airbnb listing reviews in Arabic
Airbnb listing - Reviews

Notice for example, how the account dropdown is on the left and the red reserve button is also on the left.

The obvious solution

The obvious solution for implementing a RTL layout alongside the existing LTR variant is to do it manually with CSS. Both of the projects I worked on did just that.

On one project, RTL specific HTML classes were appended based on the current language.

const Footer = ({ language }) => {
const footerClass = language === 'ar' ? 'footer-rtl' : 'footer'
return (
<footer className={footerClass}>
...
</footer>
)
}

export default connect((state) => ({
language: getLanguage(state)
}))
.footer-rtl {
flex-direction: row-reverse;

&__copright {
text-align: right
}
}

On the other, an HTML class (right-to-left) was added to the body and different CSS rules were applied based on the presence of this class

.footer {
.right-to-left & {
flex-direction: row-reverse;

&--copyright {
text-align: right;
}
}
}

These solutions were put in place by the developers who worked on the projects before us. We would have continued using the conventions they set up but then we found a web feature that made most of it unnecessary.

The dir attribute

dir (MDN) is an HTML attribute for specifying the directionality of the element.

If we specify dir="rtl" on an element, the browser will align the text to the right. It also reverses the direction of elements laid out using flexbox. For example, if flex-direction: row is set on an element, when dir="rtl" is set this will be rendered as if it was flex-direction: row-reverse.

This means that most of the CSS in the examples above were redundant! Moreover, the dir attribute is inherited by child elements. So if we set it on the html element, the directionality of the entire page is changed in one go!

Recording of browser running the example Counter app code
Switching between ltr and rtl

Styling dir attribute

Of course, there are still some things that need to be styled manually like icons and design elements like the cut corner in the Card component above. For this, we used a CSS attribute selector (MDN) to detect when the dir attribute was set and apply the styling accordingly.

[dir="rtl"] & {
@include cornercut("left");
}

The outcome

On one project, the RTL layouts were not being used since they pulled out of that market. So we decided to get rid of them, which let us remove a lot of code.

A screenshot of Azure dev ops showing the code diff after removing RTL layouts
Less code is always a win 💪

On the other, we slowly migrated to using the dir attribute together with CSS attribute selector. This also reduced a lot of the CSS we had.

Takeaways

Which web feature do you think is underrated?

Frontend undefined logo