RTL CSS with Sass

Supporting both right-to-left (RTL), often bi-directional (BiDi), and left-to-right (LTR) renderings of Web pages can be complicated. However, including a CSS preprocessor (such as Sass or LESS) to your workflow can simplify things a lot.

I have worked on three major versions of Microsoft's homepage and as you would expect, it supports quite a few locales (approximately 100). As a result, it needs to provide full support for RTL languages.

Microsoft homepage
Microsoft's homepage - English - United States (en-us) vs. עברית - ישראל (he-il)

Mirroring the layout

Converting a LTR layout to RTL is fairly straight forward. In most cases, all you have to remember is "left is right and right is left." For example, if an element is normally floated to the left, float it to the right instead. This logic continues with positioning, margin, padding, text alignment, etc. The result is a layout mirroring the original.

There can be a few exceptions (such as positioning of image sprites) so a blind find-and-replace could cause unexpected issues. Additionally, conscious decisions not to mirror are sometimes made. For example, in the above image, the tile (in this case featuring Office 365) is almost always positioned on the left hand side of the slideshow which allows the background images to be reused across locales, saving on production costs.

Common approaches

Some common approaches are manually creating/maintaining two versions of the style sheets (extra effort) or by creating an override style sheet (extra effort and page weight) for RTL (read more). But why go through the extra effort if you don't have to?

div {
   float: left;
   text-align: left;
   margin: 0 1em 0 2em;
   padding-right: 1em;
}
Example CSS for LTR.
div {
   float: right;
   text-align: right;
   margin: 0 2em 0 1em;
   padding-left: 1em;
}
Example CSS updated for RTL.

Sass helpers

CSS preprocessors, like Sass, are useful for many things. I have used other methods, such as custom ASP.NET pages, to render out CSS based on the locale's text direction, however Sass makes creating this capability straight forward and gives you many other benefits. Using my few simple Sass variables, functions, and mixins described below, should help you simplify your RTL CSS workflow. Let me know how it goes!

div {
   float: $left;
   text-align: $left;
   margin: dir-values(0 2em 0 1em);
   padding-#{$right}: 1em;
}
Example CSS updated to use Sass helpers.

List of features

After importing my directional.scss file, all you have to configure is the $dir variable (setting it to rtl or ltr) and then make use of the other variables, functions, and mixins.

Variables
  • $dir
    $dir: rtl;
    .icon.icon-star {
       background-image: url(sprite-#{$dir}.png);
    }
  • $left
    text-align: $left;
  • $right
    padding-#{$right}: 1em;
Functions
  • if-ltr($if, $else:null)
    margin: 0 if-ltr(!important);
    content: if-ltr('left-to-right', 'right-to-left');
  • if-rtl($if, $else:null)
    background-image: url(sprite#{if-rtl('-rtl')}.png);
    content: if-rtl('right-to-left', 'left-to-right');
  • dir-values($values)
    margin: dir-values(0 2em 0 1em);
Mixins
  • if-ltr {}
    @include if-ltr {
       p {
          // some css...
       }
    }
  • if-rtl {}
    @include if-rtl {
       // some css...
    }

View on GitHub

3 Responses

Leave a comment or contact me on Twitter @TysonMatanich

  1. This is great! Thanks Tyson, for the simple yet elegant solution for developing RTL websites!

  2. Svetla Velichkova

    Hey Tyson,

    it’s a great article and I really would love to use this way, just I have one question. I am developing a really big project and how do I change the $dir variable dynamicly? When the user chooses his language and how could I change it inside the css? If he chooses rtl language the dir should change to $dir=rtl; right?

    • You would need to save off two versions of your style sheets. One with $dir set to ltr and the other with it set to rtl. You could then place the files in different directories making it easy to switch between.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>