Building a Right-to-Left Web Platform

The basics and the caveats on building a right-to-left compatible web platform.

Tamanna
8 min readJun 16, 2021
Photo by Nick Fewings on Unsplash

When you have been reading, writing and looking at things from a LTR (left-to-right) perspective your whole life, things might get a little strange and even not looking right, when you start building the user interfaces of a RTL (right-to-left) web platform in a daily basis.

When we (the frontend engineering team), first started building TAMANNA, we knew from the start that it would be a multi-lang platform and that the Arabic language would be one of the featured languages. Which was a good start, because we didn’t have to introduce RTL to the platform in a later stage, thus saving us from a good portion of tech debt.

The first step to introduce RTL

We just need to change the direction in the html tag and it will be ready…

Most of us working in the software engineering field, know for a fact that when a phrase starts off something like “we just need to…”, the probabilities of it being accurate are pretty low. But regardless of that, that comment was made in the first meetings by one of us.

Needless to say, that it was incredibly wrong. Yes, it will solve more than 50% of your problems and it is a really good starting point, and in our opinion, the right start, but obviously it isn’t enough to build a product of TAMANNA’s dimension.

Problems solved by adding dir=”rtl” to the html tag:

  • Every block element and table columns will now start on the right and flow from the right to left;
  • The text will also flow from right to left;

Changing document’s direction isn’t enough

After adding changing the document’s direction

So, once we added this, the platform already looked quite different and like a real RTL product. But something didn’t look quite right, the spacing and some items positioning didn’t have the same visual effect as in the LTR version.

The problem was quickly found, we were using physical CSS properties to add spacing and positioning to some elements. But what are these properties anyway?

margin-left, margin-right, padding-left, padding-right, left, right...

Basically, every time you you are defining any CSS property with the keywords left or right, you are using physical properties, which as you might be already wondering, don’t really work well with RTL. This happens because when you change the document’s direction, right and left, still mean the same, when in reality you want them to reverse.

Logical Properties

What can you do to avoid using these so called physical properties then? You probably already guessed by this section’s title, and yes, logical properties are the solution to our spacing problems! And even the positioning ones if your goal is to only support modern browser.

CSS Logical Properties and Values is a module of CSS introducing logical properties and values that provide the ability to control layout through logical, rather than physical, direction and dimension mappings.

These properties physical values, depend on the direction defined in the document. And so, they will visually reverse depending if the document’s direction is RTL or LTR.

Most of these properties, make use of the keywords end and start to specify their physical value, for instance, padding-inline-end instead of padding-right and padding-inline-start instead of padding-left .

TAMANNA’s README.md highlight

These are some examples that we introduced inside the TAMANNA’s README.md file, pretty much as soon as we found out that using physical properties were a problem.

So that everyone is aware of possible logical properties to use instead of the more usual, physical ones.

Comprehensive list of logical properties here.

What about positioning?

After reversing left/right properties and using logical properties

For positioning, meaning the usage of left or right, we could to use the same strategy as before (logical properties). But unfortunately the browser support for inset-inline/inset-block is not too high at the time of writing this post (~67%), so we opted for a different and more secure strategy.

Our goal was to somehow, reverse the physical properties depending on the document’s defined direction, since we didn’t want to use logical CSS properties this time.

So we took a step back to look at existing solutions out there. And since we were using Styled Components (CSS in JS lib) to style our platform, we found a good looking plugin (stylis-plugin-rtl), that filled our needs. What this lib does is, whenever the direction is set to RTL, it reverses all the paddings/margins/positioning values that are defined inside a Styled Component.

The property left becomes right , padding-right becomes padding-left and so on. This doesn’t only help in positioning, but it also helps a lot on preventing UI related bugs, whenever a sneaky padding-left passes through the code review and enters production.

Should icons flip?

In TAMANNA and also in most of RTL compatible platforms there are 3 types of icons. And the answer to title’s question depends on what category does the icon in question lays under.

1- Bidirectional icons, are the ones that look the same in RTL and LTR.

Sample of bidirectional icons used in TAMANNA

2- Unidirectional icons, are the ones that should rotate depending on the document’s direction, because they usually have different meanings depending on where they are pointing.

Sample of unidirectional icons used in TAMANNA

3- Brand Icons, these icons represent brands or entities whose logo should remain the same, regardless of direction or language.

Sample of brand icons used in TAMANNA

After making this icon classification, what we did at TAMANNA was creating an Icon component that served as our source of truth and from which all our icons are created from. And also a CSS rule that would flip the icon, in case of the document’s direction being RTL.

Sample of an Icon component that is RTL compatible

External Components

Most external components/libs that you may use in your project, are most certainly not ready to be applied in both RTL and LTR context. But we are engineers, and this is not obviously not a valid excuse for not showing the interfaces as the users expect them.

For us at TAMANNA, the most challenging external component to work with (direction’s wise), was the Carousel. When we were first asked to introduce a Carousel in our platform, we didn’t want to reinvent the wheel, and so we looked for some already existing solutions out there. We ended up choosing react-responsive-carousel, which is an open source piece of software that seemed to resolve our problems (or at least most of them).

English and Arabic versions of TAMANNA’s carousels

English and Arabic versions of TAMANNA’s carousels

As you can see in the image above, both for the English and Arabic version, the actions and content seem to have the same meaning, and that’s exactly what we were looking for when building this component.

The main points that we had to change here for it to behave as it is now were:

  • Reversing the images array (so that we show the same products in the first slide for both versions);
  • Disable the NEXT/PREVIOUS arrows for the first slide, depending on the document’s direction;
  • Add specific behaviours for onClick handler to the NEXT/PREVIOUS arrows depending on the document’s direction.

The final touches

By this point, everything looked quite nice. But it’s never so simple, in a matter of days, a few RTL related bugs were found.

Example of a broken input in RLT

In the gif above, we can check that something seems awfully wrong with the credit card number input. And that’s simply because in Arabic, the numbers are written in the same way that any other LTR language. When I was actually trying to write down “4111 1111 1111 1111”, the numbers were being left behind.

So what’s the real problem here? For styling/flexibility purposes, it was used a text input to have the credit card number written, so the browser treats it the same way as any string and will try to display in in a RTL manner.

The trick here, was to append an invisible unicode, the left-to-right mark, to the input text, so that the browser treats this input as it was a LTR piece of text. That way, the number will be written as it is supposed to.

Code sample showing the LTR_MARK in action
When in reality we wanted to show the number:
+965 2221 6656

The same was happening with the phone number on the image above, we wanted to show +965 2221 6656, but the number was being flipped, as the browser treats it as any given text.

So we had to extract the number to a separate component, and change it’s direction, so it would always be LTR.

Key Notes

If you are building a RTL compatible web application, you should definitely follow these points, and you will be in right track:

1- Change the document’s direction depending on the present language;

2- Make use of Logical CSS Properties;

3- Find a way (maybe a lib or a global CSS rule) to reverse left and right properties;

4- Classify your icons and reverse the ones that are unidirectional (besides the brand ones).

5- If you have external components, take a closer look and check their RTL compatibility;

6- Check for any numbers that you are showing in your website, and if they are being presented in the correct way for both RTL and LTR.

Conclusion

With this post, our intent is to show how we at TAMANNA, proceeded to build a platform that behaves similarly in both LTR and RTL. Showing not only what we did, but how we did it, and how we got to those solutions.

If you have any further suggestion on how we can improve our current solution, of even something that you don’t agree with, feel free to comment or reach us in any way.

In case you want to join a team of engineers that uses the latest and possibly the best practices around the web or even just read another post on how we do things here, keep an eye on TAMANNA and we will see you soon.
(And yes, we are hiring!)

Written by: Pedro Figueiredo, Frontend Engineer

--

--

Tamanna

Creating Fashion and Beauty Digital Marketplace for Businesses Across the Middle East 🥷🏻🚀