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.
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?
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!
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... }
Further reading
- Inline-block for vertically aligned grids by Tyson Matanich