Bidirectional Text (BiDi)
debt(d8/e6/b5/t7)
Closest to 'silent in production until users hit it' (d9), scored d8 because while no listed detection tools exist and BiDi bugs typically surface only when actual RTL users submit content, careful review with RTL test data can catch some issues before production.
Closest to 'cross-cutting refactor across the codebase' (e7), scored e6 because the fix (CSS logical properties, dir='auto', <bdi>) is well-defined but must be applied across all stylesheets and templates — more than one component but not architectural.
Closest to 'persistent productivity tax' (b5), because once RTL support is needed, every new UI component must consider logical properties, icon mirroring, and direction — slowing many work streams without redefining system shape.
Closest to 'serious trap' (t7), grounded in the misconception that dir='rtl' on body is sufficient — the obvious approach handles text direction but silently fails to mirror layout, contradicting developer intuition that a single direction attribute should cascade.
Also Known As
TL;DR
Explanation
Unicode's Bidirectional Algorithm (UBA) determines the visual order of characters in mixed-direction text. Arabic and Hebrew scripts write right-to-left; Latin, CJK, and most scripts write left-to-right. When LTR text appears inline within an RTL paragraph (or vice versa), the browser's BiDi algorithm reorders characters for display. Developers encounter BiDi issues when: concatenating strings of mixed directionality, rendering user-generated RTL content in LTR UI (or vice versa), displaying numbers alongside RTL text (numbers are always LTR), and using text-align or float assumptions that break in RTL layouts. CSS dir='rtl' or the direction property sets the base direction for a block; the dir='auto' attribute lets the browser infer direction from content. PHP's mb_convert_encoding and intl's Normalizer handle Unicode correctly; the main PHP concern is ensuring UTF-8 throughout the stack.
How It's Exploited
Common Misconception
Why It Matters
Common Mistakes
- Concatenating RTL and LTR strings without Unicode directional formatting characters — the BiDi algorithm can produce surprising reordering at string boundaries.
- Using margin-left/margin-right instead of margin-inline-start/margin-inline-end — physical properties do not flip for RTL layouts.
- Not testing with actual RTL content — placeholder text in a dev environment is usually LTR; BiDi bugs only appear with real RTL user content.
- Assuming text-align: right is the same as dir='rtl' — direction affects more than alignment: it affects punctuation placement, list marker position, and line wrapping.
Avoid When
- Describing single-direction text layouts (e.g., a purely English document or a purely Arabic document) where no mixing of LTR and RTL content occurs.
- Troubleshooting font rendering or character encoding errors that are unrelated to text direction—BiDi applies to logical ordering, not glyph display or byte encoding.
- Addressing keyboard input or IME (input method editor) behavior, which is a separate i18n concern from visual text directionality.
- Discussing CSS layout features like flexbox or grid that happen to adapt to RTL contexts via the direction property alone, without mixing script directions.
When To Use
- Your application supports Arabic, Hebrew, or Persian users and must display user-generated content or mixed LTR/RTL text without breaking layout or readability.
- You're concatenating strings programmatically (usernames with timestamps, search queries with results) and some inputs may be in RTL scripts—use explicit directionality markers or the dir attribute to prevent character reordering bugs.
- Your UI includes inline numbers, punctuation, or LTR brand names within RTL paragraphs, and you need the Unicode Bidirectional Algorithm to handle visual ordering correctly.
- You're localizing a web app for multiple markets and need CSS or HTML direction controls that adapt reliably across LTR and RTL locales without duplicating layout code.
Code Examples
<!-- Physical CSS — breaks in RTL layouts -->
<style>
.sidebar { float: left; margin-right: 20px; } /* won't flip for RTL */
.icon { padding-left: 8px; } /* won't flip for RTL */
</style>
<!-- User content without direction hint -->
<p><?= htmlspecialchars($userContent) ?></p> <!-- Arabic content renders wrong -->
<!-- Logical CSS — automatically adapts to writing direction -->
<style>
.sidebar { float: inline-start; margin-inline-end: 20px; } /* flips for RTL */
.icon { padding-inline-start: 8px; } /* flips for RTL */
</style>
<!-- User content with automatic direction detection -->
<p dir="auto"><?= htmlspecialchars($userContent) ?></p>
<!-- <bdi> isolates inline user content from surrounding direction -->
<span>Posted by <bdi><?= htmlspecialchars($username) ?></bdi></span>