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: side-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');
  • side-values($values)
    margin: side-values(0 2em 0 1em);
  • corner-values($values)
    border-radius: corner-values(1em 2em 3em 4em);
    border-radius: corner-values(1em 2em 3em);
    border-radius: corner-values(1em 2em);
Mixins
  • if-ltr
    @include if-ltr {
      p {
        // some css...
      }
    }
  • if-rtl {}
    @include if-rtl {
      // some css...
    }

View on GitHub

Further reading