Jens Oliver Meiert

CSS: How to Host Right-to-Left Styling

Post from September 30, 2010 (↻ September 27, 2020), filed under .

This and many other posts are also available as a pretty, well-behaved ebook: On Web Development.

This post is partially outdated.

For international projects, don’t use separate style sheets for right-to-left (RTL) styling: use natural (@dir) or artificial (@id, @class) hooks instead. The only exception are unbearable performance issues due to hundreds of RTL rules.

I recommended this earlier when sharing a few RTL tips but do only here explain in a bit more detail. A side note, the focus of the post lies on projects with a global audience whose majority reads from left to right. If you are working on a site solely and forever available in, say, Hebrew, Arabic, and Danish, you may want to base defaults on RTL and customize styling for LTR. You get the idea.

The reasons why you don’t want custom RTL style sheets are maintainability and ease of use. I don’t get tired saying that: From a maintenance standpoint you want to include—note: you can still use more—one style sheet in your documents, and that style sheet should use a reasonable name. The point is that you want to reduce the probability of updating CSS references, and that everybody on your team knows and remembers what style sheet to use.

So what’s the deal with RTL styling?

<!DOCTYPE html>
<html lang="en">
  <link rel="stylesheet" href="default.css">
  <p>This is only a test.

Let’s say you have a left padding on the paragraph.

p {
  padding: 0 0 0 1em;

So what’s the best way now to deal with your Arabic version of this page? (Machine translation to the rescue.)

<!DOCTYPE html>
<html lang="ar" dir="rtl">
  <link rel="stylesheet" href="default.css">
  <p>هذا ليس سوى اختبار.

The bit of padding you’re setting on your p elements should appear on the right.

Now, the simplest solution is this:

p {
  padding: 0 0 0 1em;

html[dir='rtl'] p {
  padding: 0 1em 0 0;

The markup itself remains the same, the style sheet stays the same, no need for special documentation, no need for anyone to remember anything (except for, which kind of enforces itself, setting @dir).

Unfortunately, some older user agents may not recognize the html[dir='rtl'] selector. If that is a problem for you you’ll need an alternative hook, like

<!DOCTYPE html>
<html lang="ar" dir="rtl" id=”rtl”>
  <link rel=”stylesheet” href=”default.css”>
  <p>هذا ليس سوى اختبار.

Note that not every flavor of HTML permits an ID on the html start tag. HTML 5 does.

In order to cater for RTL, default.css would then simply say (until @dir can be used instead)

p {
  padding: 0 0 0 1em;

#rtl p {
  padding: 0 1em 0 0;

As you will have noticed, complexity slightly increased: People working on these pages will need to remember to set the id="rtl" hook in order to achieve proper styling. The modification is still simple and easy to remember, and we’re talking about a temporary markup modification, not a permanent one as custom RTL style sheets introduce them (an unfortunate practice “frameworks” like 960 Grid System prefer).

In the case of separate RTL style sheets you will need to remember to use a different style sheet,

<!DOCTYPE html>
<html lang="ar" dir="rtl">
  <link rel="stylesheet" href="default.rtl.css”>
  <p>هذا ليس سوى اختبار.

and you will also need to maintain that extra style sheet. I’ll spare you examples for that, like what you’d need to do when changing the sample padding to 2em.

In complex projects the impact of either practice is obviously bigger. You will also see practices emerge that exaggerate pain points. For example, I’ve worked on one large project in the past where an internal framework offered RTL functionality via a separate style sheet. Now that particular framework took care of basic styling and was not touched when developing custom sites, i.e. such sites included the particular framework plus an additional style sheet for the site itself. What I could observe was that some developers included the RTL version of the framework, but for additional styling they did not create an RTL version of the additional, custom style sheet, but set up RTL class names like .rtl_foo for the RTL version of .foo.

In other words,

Imagine how such RTL documents looked like, and think about how messy it became to understand what was done, how, and where.

(The recommendation applied to this last case means a framework.css and a custom.css, and custom.css to use html[dir='rtl'] .foo for RTL deviations.)

Don’t use separate style sheets for RTL styling.

Update (November 11, 2018)

A late note, the situation improves with CSS Logical Properties; these remove some former inherent directionality and with that make it possible to write style sheets that work with both LTR and RTL without special modifications.

About Me

Jens Oliver Meiert, on April 29, 2020.

I’m Jens Oliver Meiert, and I’m a web developer and author. I love trying things (sometimes involving philosophy, art, or adventure). Here on I share some of my views and experiences.

If you have a question or suggestion about what I write, please leave a comment or a message.

Comments (Closed)

  1. On September 30, 2010, 17:08 CEST, David said:

    Brilliant as always Jens! Very well explained and points well illustrated. Would be curious to know how UX is effected by simply flip flopping the layout, etc. Do RTL users follow a mirror copy of page scanning habits as LTR users? Future post perhaps?

  2. On September 30, 2010, 17:33 CEST, Vladimir Carrer said:

    Interesting concept, thank you for sharing.

  3. On September 30, 2010, 19:03 CEST, Gabri said:

    lately i was working on a Project that includes LTR & RTL styling and i used the same exact method you mentioned here using html[dir=’rtl’] selector and it was very easy to use and to maintain.

  4. On October 1, 2010, 5:32 CEST, Ali Sattari said:

    As someone who deals with RTL on a daily basis, I would prefer to have an extra style sheet which contains only rules and properties that are affecting direction and simply override them.
    That would be usually less than 5% of whole style sheet.
    This way main style sheet is LTR, no need to use attribute selectors or extra ids or classes in markup and you get to load the extra style sheet just when it is needed.

  5. On October 1, 2010, 21:51 CEST, Jens Oliver Meiert said:

    David, thanks—the short story is, yes, you can pretty much flip the layout. However there are indeed a few more things to write about and you make me consider doing so 😊

    Ali, I see your point and I generally understand the logic to be tempting. I think the 5% you mention are realistic—mileage may vary, up to 15% I’d say—, however that is something I see exactly as a plus when it comes to making an LTR style sheet RTL-ready. Focus on how much simpler it is to work with one style sheet, too (if you had only one before, you’d otherwise, in a way, double complexity). Not only does that one style sheet come with a few maintenance advantages but it’s also just easier to use. I guess I’m about to repeat what I wrote before.

  6. On October 5, 2010, 14:34 CEST, Hassan said:

    I use WordPress, and it automatically link the rtl.css file if it’s present. I think it’s the simplest way. Most of the time it doesn’t get larger than 20 or 30 lines.

Read More

Have a look at the most popular posts, possibly including:

Cover: CSS Optimization Basics.

Perhaps my most relevant book: CSS Optimization Basics (2018). Writing CSS is a craft. As craftspeople we strive to write high quality CSS. In CSS Optimization Basics I lay out some of the most important aspects of such CSS. (Also available in a bundle with Upgrade Your HTML and The Web Development Glossary.)

Stay up-to-date? Follow me by feed or on Twitter.

Looking for a way to comment? Comments have been disabled, unfortunately.

Found a mistake? Email me,

You are here: HomeArchive2010 → CSS: How to Host Right-to-Left Styling

Last update: September 27, 2020

“Work is love made visible.”