RTL Development Guide
Master RTL-first development with logical properties, best practices, and proven patterns for building truly bidirectional interfaces.
The RTL-First Philosophy
What is RTL-First?
RTL-first development means building interfaces that work seamlessly in both left-to-right (LTR) and right-to-left (RTL) directions from the start, without requiring special handling or conditional logic.
Core Principles
- Logical over Directional: Use logical properties (start/end) instead of directional ones (left/right)
- Single Source of Truth: One codebase works for all directions without conditional logic
- Test Both Directions: Always verify components in both LTR and RTL modes
- Accessibility First: RTL support should maintain full accessibility
Logical Properties
Logical properties are the foundation of RTL-first development. They refer to the start and end of content flow, rather than physical left and right positions.
Before and After
Complete Mapping Reference
Why Logical Properties?
When you use ms-4 (margin-inline-start), it automatically becomes margin-left in LTR and margin-right in RTL. No conditional logic needed!
Common Patterns
Learn the most common layout patterns that work seamlessly in both directions.
Layout Patterns
Flex Layouts
Flexbox with logical properties works automatically in both directions. Avoid using flex-row-reverse for RTL - just use logical spacing instead.
Icon Mirroring
Some icons should mirror in RTL (directional arrows), while others should not (settings, user icons).
Do
- ✓ Arrows (→ ←)
- ✓ Chevrons (› ‹)
- ✓ Forward/Back navigation
- ✓ Undo/Redo
- ✓ Directional pointers
Don't
- ✗ Settings/gear icons
- ✗ User/profile icons
- ✗ Search icons
- ✗ Checkmarks
- ✗ Media controls (play, pause)
- ✗ Close (X) buttons
Keyboard Shortcuts in RTL
Keyboard shortcuts are neutral technical elements that don't participate in text direction flow.
Core Principle
Shortcuts remain in the same physical position (end of UI element) in both LTR and RTL, but text flows naturally in its direction.
Examples
- • LTR: "Search... ⌘K"
- • RTL: "⌘K ...بحث"
Critical: Internal Flex Reversal
If the kbd uses inline-flex, add rtl:flex-row-reverse to prevent the shortcut content from reversing (⌘K becoming K⌘).
Best Practice
Use ms-auto to push shortcuts to the end, and rtl:flex-row-reverse if kbd has internal flex layout.
Using the Direction Hook
Access and control the current direction programmatically when needed.
When to Use
- Building direction toggles or language selectors
- Conditionally rendering direction-specific content
- Handling complex animations that need direction awareness
- Logging or analytics based on direction
Testing RTL Support
Always test your components in both directions to ensure proper RTL support.
Visual Testing with Playwright
Manual Testing Checklist
- Toggle direction and verify all spacing looks correct
- Check that text alignment follows the direction
- Verify icons mirror appropriately (or don't when they shouldn't)
- Test keyboard navigation in both directions
- Ensure animations and transitions work correctly
Live Example
Toggle the direction using the button in the header to see how logical properties work in action.
LTR (English)
User Name
This text adapts to direction
RTL (العربية)
User Name
This text adapts to direction
Migration Guide
Converting an existing LTR-only application to RTL-first is straightforward with systematic replacement.
Migration Steps
- Search for directional properties (ml-, mr-, pl-, pr-, left-, right-)
- Replace with logical equivalents (ms-, me-, ps-, pe-, start-, end-)
- Update text alignment (text-left → text-start, text-right → text-end)
- Fix absolute positioning (left-0 → start-0, right-0 → end-0)
- Update border radius classes (rounded-l → rounded-s, etc.)
- Review flex layouts and remove unnecessary flex-row-reverse
- Test thoroughly in both LTR and RTL
Best Practices
Do
- ✓ Use logical properties everywhere
- ✓ Test in both directions regularly
- ✓ Use the direction toggle during development
- ✓ Mirror directional icons appropriately
- ✓ Keep accessibility in mind
- ✓ Use Flexbox and Grid for layouts
Don't
- ✗ Use directional properties (ml-, mr-, left-, right-)
- ✗ Add conditional logic for direction
- ✗ Forget to test RTL mode
- ✗ Mirror all icons (some shouldn't)
- ✗ Rely solely on left/right positioning
- ✗ Use text-left or text-right
Lessons Learned from Real-World Development
Practical insights and solutions to common RTL challenges discovered while building Noor UI components.
1Lesson 1: Keyboard Shortcuts Reverse in RTL
The Problem
Keyboard shortcuts like ⌘K can reverse to K⌘ in RTL mode, confusing users.
The Solution
Wrap shortcuts in a nested structure: outer span for positioning (uses logical properties), inner span for text direction (dir="ltr").
This ensures shortcuts stay readable (⌘K) while positioning correctly at the end of menu items.
2Lesson 2: Positioning ≠ Text Direction
The Challenge
When you need both correct positioning AND text direction control, dir="ltr" on a single element breaks logical properties like margin-inline-start.
The Fix
Separate concerns: outer element handles position with logical properties (ms-auto), inner element handles text flow with dir="ltr".
Result: Shortcuts appear at the correct edge (right in LTR, left in RTL) with proper text direction.
3Lesson 3: Transform Animations Need RTL Variants
The Issue
CSS transforms like translateX don't automatically flip in RTL. A switch sliding right in LTR will still slide right in RTL.
The Pattern
Add RTL-specific transform classes: translate-x-4 for LTR becomes -translate-x-4 for RTL.
This makes animations feel natural in both directions.
4Lesson 4: Direction Check, Not Locale Check
The Mistake
Checking locale === 'ar' to determine RTL only works for Arabic. This breaks support for Hebrew, Urdu, Farsi, and other RTL languages.
The Correct Pattern
Always check direction === 'rtl' instead of locale === 'ar'. The direction property works for ALL RTL languages, making your components truly international.
This ensures your components work for ALL RTL languages (Arabic, Hebrew, Urdu, Farsi, etc.), not just Arabic.
Last Updated: 2025-11-29
Found a new RTL pattern? Please contribute to help the community!