Building a Right-to-Left Web Platform
The basics and the caveats on building a right-to-left compatible web platform.
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
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
.
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?
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.
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.
3- Brand Icons, these icons represent brands or entities whose logo should remain the same, regardless of direction or language.
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.
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
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.
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.
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