Direction (RTL)
Every component ships right-to-left support out of the box. Like shadcn/ui,
Direction is a guide rather than an installable component: set the document
dir attribute and the components mirror
automatically, because they are authored with CSS logical properties instead of
physical left/right
utilities. No extra CSS, no wrapper components, no post-processing — it just works.
Enabling RTL
Set dir="rtl" on the
<html> element to apply RTL to the
entire page. The lang attribute should
match the language you are rendering.
<html lang="ar" dir="rtl">
You can also scope the direction to any subtree. This is useful for rendering a single RTL widget inside an otherwise LTR page, or for language-switcher previews.
{{-- Scope RTL to a single component, not the whole page --}}
<div dir="rtl">
<x-ui.card>…</x-ui.card>
</div>
Switch the preview workbench on any component page to RTL to see it mirror live — no code changes required.
Side by side
The same markup, rendered once LTR and once RTL. Both panels share identical
HTML — only the dir attribute differs.
Left to right (dir="ltr")
Right to left (dir="rtl")
How it works
CSS logical properties replace the concept of "left" and "right" with inline-start and inline-end. The browser resolves those to physical directions based on the element's writing direction, so the same class list works in both LTR and RTL contexts.
| Use this (logical) | Not this (physical) | Resolves to |
|---|---|---|
ps-4 / pe-4 |
pl-4 / pr-4 |
padding-inline-start/end |
ms-2 / me-2 |
ml-2 / mr-2 |
margin-inline-start/end |
start-0 / end-0 |
left-0 / right-0 |
inset-inline-start/end |
text-start / text-end |
text-left / text-right |
text-align: start/end |
border-s / border-e |
border-l / border-r |
border-inline-start/end |
rounded-s-* / rounded-e-* |
rounded-l-* / rounded-r-* |
border-start/end-radius |
All primitives in this system follow this rule. If you are building a custom component on top of them, use the same logical utilities so your component automatically inherits RTL support.
- Interactive components mirror keyboard semantics too — arrow keys in tabs, menus, sliders, carousels, and the calendar swap with the writing direction automatically.
-
Every primitive exposes a stable
data-slotattribute, making CSS overrides direction-aware without targeting physical sides.
Writing RTL-safe custom components
Follow the same conventions when building your own Blade components on top of these primitives.
Use logical spacing utilities
pl-*,
pr-*,
ml-*,
mr-* with their logical equivalents.
Tailwind ships these out of the box — no plugin required.
Mirror directional icons
rtl:-scale-x-100 utility
(visible in the live demo above on the breadcrumb chevron).
Keep numbers and code LTR
<bdi> or apply
dir="ltr" to the specific element.
Test with the RTL toggle
dir="rtl"
onto the preview frame and the component should mirror cleanly.
Gotchas
Warning
rtl:-scale-x-100 to every icon that
points left or right. Icons that are symmetric (search, close, spinner) need no
change.{{-- chevron that mirrors in RTL --}}
<svg class="size-4 rtl:-scale-x-100" …>…</svg>
{{-- search icon — symmetric, no mirroring needed --}}
<svg class="size-4" …>…</svg>
Note
dir="ltr"
or a <bdi> tag removes any ambiguity
and prevents odd wrapping in mixed-direction sentences.Note
dir.
Chart libraries, date-pickers from other ecosystems, and embedded iframes may
have their own internal LTR assumptions. Test each integration independently.Note
pl-4 and
ps-4 on the same element creates
specificity confusion. Pick one convention and be consistent — all shipped
primitives use logical-only.