---
title: Automatically creating RTL CSS
date: 2016-06-04
tags: [code, css, a11y]
description: Most western scripts are read from left to right (LTR), so this is what many web developers think about when writing CSS. But some scripts, such as Arabic or Hebrew, are read from right to left (RTL).
---

## What is it and why does it concern me?

Most western scripts are read from left to right (LTR), so this is what many
web developers think about when writing CSS. But some scripts, such as Arabic
or Hebrew, are read from right to left (RTL). But it is not only about the text
direction. The complete layout should also be mirrored to match it.

So say you want to write CSS that can be used with both text directions. What
do you have to think about?

## The problem

HTML and CSS have advanced support for different text directions. You can use
the [`dir`
attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
to specify text direction and the
[`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi) and
[`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
elements allow for fine-grained control.

The only issue is that `left` and `right` are actually physical directions and
will not change with text direction, so any `float: left` or `margin-right:
1em` will not adapt with the text direction.

## The solution

Just as relative units such as `em` or `%` are better than absolute `px`,
relative directions like `start` and `end` are preferable to `left` and
`right`. Unfortunately, they are not (yet) available. But the W3C is working on
it and `start` / `end` are already available for the [`text-align`
property](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align) in many
browsers.

## The workaround

As long as the proper solution is not available, here is a simple way to
convert a LTR stylesheet to RTL.  I am not exactly sure that this is the
complete list, but it should be sufficient:

-   Replacing all occurrences of the string `left` by `right` and vice versa:

    ```sh
    sed 's/left/TMP/g;s/right/left/g;s/TMP/right/g' ltr.css > rtl.css
    ```

    Just include this as a final build step, even after minification.

-   Avoid 4-value shorthands such as `margin: 0 1em 0 2em`. Instead, do
    something like this:

    ```css
    margin: 0;
    margin-right: 1em;
    margin-left: 2em;
    ```

    3-value shorthands are fine, as they use the same value for left and right.

-   Do not try to have only a single CSS file and write custom code based on
    descendant selectors. That will just make everything extremely complicated.

-   Do not try to have a LTR stylesheet and a second, smaller RTL stylesheet
    that only contains the necessary overwrites. The only case where this has
    any performance benefit is when users switch from one layout to the other.
    In all other cases this is actually worse, apart from being hard to
    maintain.

## Outlook: vertical text

CSS3 will take the support for non-latin scripts even further and add support
for vertical (e.g. top-to-bottom) text. Note however that most vertical scripts
also have horizontal variants, so it is not completely necessary to support
this feature anytime soon.

One important thing to remember is that many new keywords from these specs use
abbreviations such as `vertical-rl` for "vertical-right-left". But you probably
should not mix that workaround with these new properties anyway.

## Further reading

-   <https://github.com/MohammadYounes/rtlcss>
-   <http://www.rtl-this.com/>
-   <https://www.w3.org/TR/css-writing-modes-3/>
-   <http://generatedcontent.org/post/45384206019/writing-modes>
-   <https://www.w3.org/International/articles/css3-text/>
