I've been working around a solution to easily manage LTR and RTL on the same interface.

The different solutions I knew at first:

  1. Override CSS according to direction.
  2. Use a program to transform your CSS in LTR to a new RTL file.
  3. Start from a body { transform: rotateY(180deg) }.

1. Override CSS according to direction

This solution is painful for developers. You have to think of overriding ever CSS that will not flip properly.

Such as:

.title {
  float: left;
  margin-left: 10px;

body[dir="rtl"] .title {
  float: right;
  margin-left: 0;
  margin-right: 10px;

Note: Adding an attribute dir="rtl" on the <body> flips the whole interface, but you'll still need to override margins, floats, etc.

2. Use a program to transform your CSS in LTR to a new RTL file

This implies using an external program you didn't control to run on all your style files and then you have to make sure to send the LTR or RTL version accordingly to the client.

To me it felt quite unsafe to rely on this. I can't be sure it works 100% fine and it can be quite complex (from my point of view, I didn't dive into it).

3. Start from a body { transform: rotateY(180deg) }

This is the option I went for.

It felt a lot more pleasant. Almost everything is already working fine (in my test cases). I only need to work on text elements.

Here is what I came up with so far:

#app[x-dir="rtl"] {
  transform: rotateY(180deg);

#app[x-dir="rtl"] input,
#app[x-dir="rtl"] textarea,
#app[x-dir="rtl"] img,
#app[x-dir="rtl"] video,
#app[x-dir="rtl"] iframe,
#app[x-dir="rtl"] h1,
#app[x-dir="rtl"] h2,
#app[x-dir="rtl"] h3,
#app[x-dir="rtl"] h4,
#app[x-dir="rtl"] h5,
#app[x-dir="rtl"] h6,
#app[x-dir="rtl"] p,
#app[x-dir="rtl"] label {
  display: inline-block;
  transform: rotateY(180deg);
  direction: rtl;

#app[x-dir="rtl"] label input {
  transform: rotateY(0);

#app[x-dir="rtl"] .rtl {
  display: inline-block;
  transform: rotateY(180deg);
  direction: rtl;


The only thing missing after flipping the whole interface is:

  • I have to flip texts back, because they are wrong(flipped with the page).
  • Add a direction: rtl; on each tag containing content that needs to be display as RTL.

What I'm doing:

  • Generalizing as much as possible tags that for sure need to have RTL behavior and flipped back.
  • Give the developer access to a class .rtl, for edge cases (eg: I can't guess if <span> and <div> contain text or not).

Note: I use an attribute x-dir="", because dir="" flips the interface. I want full control.


  • The only one I can think of: You can't add .rtl to an element that already has a transform because it'd override. It is not additive.

Feel free to test around: DEMO


Can you think of any edge case I haven't thought of?

Is it a good way to go?

Any optimization?

Helpful links



2 Answers 2


I found a case where the solution #3 doesn't work : when you're dealing with scroll bars.

In your example, if you put a container smaller than the content, the scrollbar behave strangely in RTL, scrolling right when you press the left arrow and vice versa.

The same thing happen when you press the mouse's middle click and move to any horizontal direction.


Personally I feel #3 is the worst choice. I can only imagine all the things that can go wrong there. At the very least I would mirror the page (transform: scale(-1, 1)) instead of rotating it.

The first attempt should be to find/use a standards confirming way to do it. Unfortunately other than the your #1 solution there is currently none. Some browsers do support some proprietary properties such as Mozillas logical properties and I believe Webkit has simular ones, but that is it.

The best solution in my option is to generate the CSS using a scripting language such as SASS. Here is an article that describes a basic library can generate the RTL and LTR versions of a style sheet: RTL CSS with Sass

EDIT: Two more things:

Note: I use an attribute x-dir="", because dir="" flips the interface. I want full control.

At the very least use a standardized custom attribute with the prefix data-, i.e. data-dir.

Also keep in mind, on the web you are never "in full control". Trying to force things in web development only breaks things more.

  • \$\begingroup\$ Thanks for answering! Why do you suggest scale instead of rotate? You could have pointed out that I wasn't using a 3D transformation (adding translateZ for example) to optimize using the GPU. I think you're right, the #1 solution is the most common. Although you'd probably agree that it's a solution a lot more painful and time consuming to develop and maintain (even using SASS)? This is why I suggested another approach. You say: "I can only imagine all the things that can go wrong", I'm looking for that, because so far I haven't had any issue apart from the one I pointed out. \$\endgroup\$
    – Elfayer
    Jun 20, 2017 at 13:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.