Going Both Ways

It’s that time of the year again: Santa is getting ready to travel the world. Up until now, girls and boys from all over have sent in letters asking for what they want. I hope that Santa and his elves have—unlike me—learned more than just English.

On the Internet, those girls and boys want to participate in sharing their stories and videos of opening presents and of being with friends and family. Ah, yes, the wonders of user generated content. But more than that, people also want to be able to use sites in the language they know.

While you and I might expect the text to read from left to right, not all languages do. Some go from right to left, such as Arabic and Hebrew. (Some also go from top to bottom, but for now, let’s just worry about those first two directions!)

If we were building a site for girls and boys to send their letters to Santa, we need to consider having the interface in the language and direction that they prefer. On the elves’ side, they may be viewing the site in one direction but reading the user generated content in the other direction. We need to build a site that supports bidirectional (or bidi) text.

Let’s take a look at some things to be aware of when it comes to building bidi interfaces.

Setting the direction of the interface

Right off the bat, we need to tell the browser what direction the text should be going in. To do this, we add the dir attribute to an HTML element and set it to either LTR (for left to right) or RTL (for right to left).

<body dir="rtl">

You can add the dir attribute to any element and it will set or change the direction for the content within that element.

<body dir="ltr">
   Here is English Content.
   <div dir="rtl">الموضوع</div>
</body>

You can also set the direction via CSS.

.rtl {
    direction: rtl;
    }

It’s generally recommended that you don’t use CSS to set the direction of the text. Text direction is an important part of the content that should be retained even in environments where the CSS may not be available or fails to load.

How things change with the direction attribute

Just adding the dir attribute tells the browser to render the content within it differently.

A screenshot of a page of text, aligned to the right.

The text aligns to the right of the page and, interestingly, punctuation appears at the left of the sentence. (We’ll get to that in a little bit.)

Scrollbars in most browsers will appear on the left instead of the right. Webkit is the notable exception here which always shows the scrollbar on the right, no matter what the text direction is. Avoid having a design that has an expectation that the scrollbar will be in a specific place (and a specific size).

Changing the order of text mid-way

As we saw in that previous example, the punctuation appeared at the beginning of the sentence instead of the end, even though the text was English. At Yahoo!, we have an interesting dilemma where the company name has punctuation in it. Therefore, when the name appears in the middle of (for example) Arabic text, the exclamation mark appears at the beginning of the word instead of the end.

A screenshot of some text with the exclamation mark at the beginning of the word instead of the end.

There are two ways in which this problem can be solved:

1. Use HTML around the left-to-right content, or

To solve the problem of the Yahoo! name in the midst of Arabic text, we can wrap a span around it and change the direction on that element.

Screenshot of some code with some Arabic text wrapped in a span, which has its directions set from ltr.

2. Use a text direction mark in the content.

Unicode has two marks, U+200E and U+200F, that tell the browser that the text is in a particular direction. Placing this right after the punctuation will correct the placement.

Using the HTML entity:
Yahoo!&#x200e;

Tables

Thankfully, the cells of a data table also get reordered from right to left. Equally as nice, if you’re using display:table, the content will still get reordered.

A screenshot of some text in table cells. The cells have been reordered so the first is on the right, and the last is on the left.

CSS

So far, we’ve seen that the dir attribute does a pretty decent job of getting content flowing in the direction that we need it. Unfortunately, there are huge swaths of design that is handled by CSS that the handy dir attribute has zero effect over.

Many properties, like float or absolute positioning with left and right values, are unaffected and must be handled manually. Elements that were floated left must now by floated right. Left margins and paddings must now move to the right and the right margins and paddings must now move to the left.

Since the browser won’t handle this for us, we have a couple approaches that we can use:

CSS Only

We can take advantage of the attribute selector to target CSS to apply in one direction or another.

[dir=ltr] .module {
	float: left;
	margin: 0 0 0 20px;
}
[dir=rtl] .module {
	float: right;
	margin: 0 20px 0 0;
}

As you can see from this example, both of the properties have been modified for the flipped interface. If your interface is rather complicated, you will have to create a lot of duplicate rules to have the site looking good in both directions while serving up a single stylesheet.

CSSJanus

Google has a tool called CSSJanus. It’s a Python script that runs over the LTR versions of your CSS files and generates RTL versions. For the RTL version of the site, just serve up those CSS files instead of the LTR versions.

The script looks for keywords and value combinations and automatically swaps them so you don’t have to.

At Yahoo!, CSSJanus was a huge help in speeding up our development of a bidi interface. We’ve also made a number of improvements to the script to better handle border radius, background positioning, and gradients. We will be pushing those changes back into the CSSJanus project.

A screenshot of Yahoo mail in Arabic.

Background Images

Background images, especially for things like CSS sprites, also raise an interesting dilemma. Background images are positioned relative to the left of the element. In a flipped interface, however, we need to position it relative to the right. An icon that would be to the left of some text will now need to appear on the right.

Some icons which have been designed for right to left, and left to right languages.

If the x position of the background is percentage-based, then it’s fairly easy to swap the values. 0 becomes 100%, 10% becomes 90% and so on. If the x position is pixel-based, then we’re in a bit of a pickle. There’s no way to say that the image should be a certain number of pixels from the right.

Therefore, you’ll need to ensure that any background image that needs to be swapped should be percentage-based. (99.9% of the the time, the background position will need to be 0 so that it can be changed to 100% for RTL.)

If you’re taking an existing implementation, background positioning will likely be the biggest hurdle you’ll have to overcome in swapping your interface around. If you make sure your x position is always percentage-based from the beginning, you’ll have a much smoother process ahead of you!

Flipping Images

This is a more subtle point and one where you’ll really want an expert with the region to weigh in on. In RTL interfaces, users may expect certain icons to also be flipped. Pencil icons that skew to the right in LTR interfaces might need to be swapped to skew to the left, instead. Chat bubbles that come from the left will need to come from the right.

The easiest way to handle this is to create new images. Name the LTR versions with -ltr in the name and name the RTL versions with -rtl in the name. CSSJanus will automatically rename all file references from -ltr to -rtl.

The Future

Thankfully, those within the W3C recognize that CSS should be more agnostic. As a result, they’ve begun introducing new properties that allow the browser to manage the swapping from left to right for us.

The CSS3 specification for backgrounds allows for the background-position to be relative to other corners other than the top left by specifying keywords before each position.

This will position the background 5px from the bottom right of the element.

background-position: right 5px bottom 5px;

Opera 11.60 is currently the only browser that supports this syntax.

For margin and padding, we have margin-start and margin-end. In LTR interfaces, margin-start would be the same as margin-left and in RTL interfaces, margin-start would be the same as margin-right.

Firefox and Webkit support these but with vendor prefixes right now:

-webkit-margin-start: 20px;
-moz-margin-start: 20px;

In the CSS3 Images working draft specification, there’s an image() property that allows us to specify image fallbacks and whether those fallbacks are for LTR or RTL interfaces.

background: image('sprite.png' ltr, 'sprite-rtl.png' rtl);

Unfortunately, no browser supports this yet but it’s nice to be able to dream of how much easier this will be in the future!

Ho Ho Ho

Hopefully, after all of this, you’re full of cheer knowing that you’re well on your way to creating interfaces that can go both ways!

About the author

Jonathan Snook is an internationally-admired web designer and developer, and a gifted creator of striking designs and impeccable markup and code. He moves effortlessly from client-side, front-end work to hardcore server-side challenges, and his fluency in CSS, JavaScript, PHP and MySQL make him the “turn-to” man for many high-profile clients. Coauthor of , he writes regularly at his popular blog snook.ca. Jonathan speaks at top web conferences and also works with his partners at Sidebar Creative, makers of world-class websites and innovative applications.

Photo: Patrick H. Lauke

More articles by Jonathan

Comments