useRtl
The useRtl composable provides reactive RTL (right-to-left) direction management. It manages a boolean direction state and sets the dir attribute on a target element via the adapter pattern. Independent from useLocale — direction is a layout concern, not a content concern.
Installation
Install the RTL plugin in your app’s entry point:
import { createApp } from 'vue'
import { createRtlPlugin } from '@vuetify/v0'
import App from './App.vue'
const app = createApp(App)
app.use(createRtlPlugin())
app.mount('#app')With Options
app.use(
createRtlPlugin({
default: true, // Start in RTL mode
})
)Usage
import { useRtl } from '@vuetify/v0'
const rtl = useRtl()
// Read direction
rtl.isRtl.value // false (LTR by default)
// Toggle direction
rtl.toggle() // Now true (RTL)
// Direct assignment
rtl.isRtl.value = false // Back to LTRReactivity
| Property | Type | Description |
|---|---|---|
isRtl | Ref<boolean> | Writable ref — true for RTL, false for LTR |
toggle | () => void | Flips the current direction |
Adapter
The default Vuetify0RtlAdapter sets the dir attribute on the target element (defaults to document.documentElement). This enables native browser RTL support including CSS logical properties and the :dir() pseudo-class.
// Custom target element
app.use(createRtlPlugin({ target: '#app' }))
// Disable dir attribute management
app.use(createRtlPlugin({ target: null }))Styling
The dir attribute set by the adapter enables three approaches to direction-aware styling with utility classes:
Logical Properties (preferred)
CSS logical properties automatically flip based on dir. Use these by default:
<!-- Physical (breaks in RTL) -->
<div class="ml-4 pr-2 left-0 border-l-2">...</div>
<!-- Logical (works in both directions) -->
<div class="ms-4 pe-2 start-0 border-s-2">...</div>| Physical | Logical | CSS Property |
|---|---|---|
ml-* / mr-* | ms-* / me-* | margin-inline-start / end |
pl-* / pr-* | ps-* / pe-* | padding-inline-start / end |
left-* / right-* | start-* / end-* | inset-inline-start / end |
border-l-* / border-r-* | border-s-* / border-e-* | border-inline-start / end |
rounded-l-* / rounded-r-* | rounded-s-* / rounded-e-* | border-start-*-radius / end |
text-left / text-right | text-start / text-end | text-align |
The utility class names above use UnoCSS presetWind4 / Tailwind v4 syntax. Exact class names may vary depending on your CSS framework or preset — the underlying CSS logical properties are the same.
Direction Variants
For cases logical properties can’t handle (like translate-x), use ltr: and rtl: variants:
<!-- Mobile drawer: slides from start edge -->
<nav class="ltr:-translate-x-full rtl:translate-x-full md:ltr:translate-x-0 md:rtl:translate-x-0">
...
</nav>Symmetric Shorthand
When both sides use the same value, use inset-x-* instead of left-* right-*:
<!-- Before -->
<div class="fixed left-0 right-0 top-0">...</div>
<!-- After -->
<div class="fixed inset-x-0 top-0">...</div>Subtree Overrides
Use createRtlContext to scope direction to a subtree:
import { createRtlContext } from '@vuetify/v0'
// Create a scoped RTL context
const [useLocalRtl, provideLocalRtl] = createRtlContext({ default: true }) Direction is independent from locale. To connect them (e.g., Arabic → RTL), use a custom adapter that watches useLocale().selectedId and sets isRtl based on a language→direction mapping.
Functions
createRtlFallback
() => RtlContextcreateRtlContext
<_E>(_options?: RtlContextOptions | undefined) => ContextTrinity<_E>createRtlPlugin
(_options?: RtlContextOptions | undefined) => PluginuseRtl
<_E>(namespace?: string) => _EOptions
target
string | HTMLElement | null | undefinedTarget element or selector for dir attribute. Defaults to documentElement.