89.6 Handling Right-to-Left Text
Alright, let’s talk about Right-to-Left (RTL) text. You’ve probably been blissfully living in a left-to-right world, where everything starts at a sensible, familiar corner of the screen. Then, one day, you need to support Arabic or Hebrew, and suddenly your entire UI looks like it’s been through a matter-antimatter inversion. Welcome. It’s not actually that bad, but it’s a domain where a little knowledge prevents a lot of utterly bizarre layout bugs.
The core thing to internalize is the difference between direction and alignment. This is the hill many a good layout has died on. Direction is the big one: it’s the overall flow of the content. For an entire page or a major container, it dictates the order of not just text, but often everything else—navigation, images, the whole shebang. Alignment is the smaller, more familiar concept: is this specific chunk of text flush-left, centered, or flush-right? In an RTL context, ‘flush-left’ means something very different.
The dir Attribute is Your Foundation
Forget CSS for a hot second. The most robust, semantic way to set base direction is the HTML dir attribute. You can slap it on the <html> tag for the whole page, or on any specific container like a <div> or <p>.
<html dir="rtl">
<body>
<p>هذه فقرة باللغة العربية.</p>
</body>
</html>
Why is this better than just using CSS? Because it ensures correctness even if CSS fails to load, it’s understood by screen readers and other assistive tech, and it affects the entire nesting context. Text inside that container will now flow RTL. But here’s the kicker: so will the order of your elements if you’re using something like flexbox or grid. A flex-direction: row suddenly becomes row-but-from-the-right. This is either brilliantly convenient or a massive headache, depending on how prepared you are.
The CSS Logical Properties Revolution
This is the part where we stop the madness of writing separate stylesheets for LTR and RTL. For years, we used physical properties like margin-left, padding-right, float: left;. This is a one-way ticket to Maintenance Hell. You’d have to override every single one for your RTL layout.
CSS logical properties solve this by describing things relative to the content flow, not the physical screen. Instead of left and right, we use inline-start and inline-end. For block direction (top/bottom in a horizontal writing mode), we use block-start and block-end.
Here’s the transformation:
/* The old, physical way (don't do this for new work) */
.old-style {
margin-left: 1rem;
padding-right: 2rem;
border-left: 2px solid black;
text-align: left;
}
/* The new, logical way (do this!) */
.new-style {
margin-inline-start: 1rem;
padding-inline-end: 2rem;
border-inline-start: 2px solid black;
text-align: start; /* This is the real hero */
}
See that text-align: start? It’s genius. In an LTR context, start is left. In an RTL context, start is right. It just works. Using logical properties means 95% of your styles will automatically flip when the dir changes. You’re writing one stylesheet to rule them all.
The Bane of My Existence: Mixed Direction Content
Here’s where the designers probably didn’t think it through, and reality intrudes. You’ll have an RTL interface, but a user pastes a part number, a URL, or an English product name into an input field. Suddenly, you have an LTR phrase inside an RTL block. The Unicode bidirectional algorithm (a.k.a. the bidi algorithm) usually handles this… until it doesn’t.
The result can be a “directionality storm” where the text order becomes utterly garbled. The solution is the bdi (Bidirectional Isolation) element. It isolates its content from the surrounding directionality, allowing the text inside to determine its own direction.
<div dir="rtl">
<p>اسم المستخدم: <bdi>user123</bdi></p>
<p>آخر تحديث: <bdi>2024-05-22</bdi></p>
</div>
Without the <bdi>, the Latin text could mess with the flow of the surrounding Arabic. It’s like a force field for direction. Use it religiously around any user-generated or dynamic content whose directionality you cannot guarantee.
Testing: No, Really, You Have To
You cannot eyeball this. You will get it wrong. Set your dir attribute to rtl and then use your app. Does the layout break horribly? Good, you found the places where you used physical properties. Now fix them with logical ones.
Check your icons. An icon of a magnifying glass for “search” should probably be on the inline-start side (the right in RTL). An arrow pointing to the “next” page should point left, not right, because in an RTL context, “next” is towards the lower-numbered page. It’s a head-trip, but it’s what correct localization demands.
Finally, get a native speaker to look at it. They’ll spot awkward phrasing you’d never catch, and they’ll be the first to tell you if your beautifully flipped layout still feels… off. This stuff is complex, but getting it right is a mark of a truly polished product.