Skip to Content

RTL Layout

When a visitor views a trainer’s site in Arabic or Persian, the platform sets dir="rtl" on the <html> element. This automatically mirrors many CSS properties, but you’ll need explicit overrides for some layouts.

What dir="rtl" does automatically

The browser automatically flips these when dir="rtl" is set:

  • Text alignment — defaults to right-aligned
  • Table layout — columns flow right-to-left
  • CSS logical properties — margin-inline-start adapts to direction

What it does not flip automatically:

  • Flexbox row direction — flex-direction: row still goes left-to-right
  • Absolute/fixed positioning — left: 0 stays on the left
  • Transforms — translateX(10px) still moves right
  • Animations — slide-in-from-left still comes from the left
  • Padding/margin physical properties — padding-left stays left

CSS Module RTL overrides

Use :global([dir="rtl"]) in your CSS Modules to target RTL mode:

/* Navigation flows left-to-right by default */ .nav { display: flex; flex-direction: row; gap: 1.5rem; } /* Flip navigation for RTL */ :global([dir="rtl"]) .nav { flex-direction: row-reverse; }

Common patterns

Horizontal flexbox:

.row { display: flex; gap: 1rem; } :global([dir="rtl"]) .row { flex-direction: row-reverse; }

Absolute positioning:

.badge { position: absolute; right: 1rem; top: 1rem; } :global([dir="rtl"]) .badge { right: auto; left: 1rem; }

Margin and padding:

.icon { margin-right: 0.5rem; } :global([dir="rtl"]) .icon { margin-right: 0; margin-left: 0.5rem; }

Or use CSS logical properties (recommended):

/* Automatically adapts to text direction — no RTL override needed */ .icon { margin-inline-end: 0.5rem; }

Prefer CSS logical properties where possible. Properties like margin-inline-start, padding-inline-end, inset-inline-start, and border-inline-end automatically adapt to the text direction without needing RTL overrides.

Tailwind RTL prefix

Tailwind includes an rtl: prefix for RTL-specific utilities:

<div className="flex flex-row rtl:flex-row-reverse gap-4"> <span className="ml-2 rtl:ml-0 rtl:mr-2">Text</span> </div>

Flipping animations

Slide animations need to reverse direction in RTL:

.slideIn { animation: slideInLeft 0.3s ease-out; } @keyframes slideInLeft { from { transform: translateX(-100%); } to { transform: translateX(0); } } :global([dir="rtl"]) .slideIn { animation: slideInRight 0.3s ease-out; } @keyframes slideInRight { from { transform: translateX(100%); } to { transform: translateX(0); } }

Common RTL gotchas

Icons with directional meaning

Some icons imply direction (arrows, chevrons, progress indicators). These should flip in RTL:

.chevron { display: inline-block; } :global([dir="rtl"]) .chevron { transform: scaleX(-1); }

Icons that should not flip: play buttons, checkmarks, phone icons, search icons.

Progress bars

Progress bars that fill left-to-right should fill right-to-left in RTL:

.progressBar { direction: ltr; /* Force LTR so percentages work correctly */ } :global([dir="rtl"]) .progressBar { direction: rtl; } .progressFill { transform-origin: left; } :global([dir="rtl"]) .progressFill { transform-origin: right; }

Mobile menu slide-in direction

The mobile menu should slide in from the right in LTR and from the left in RTL:

.mobileMenu { position: fixed; top: 0; right: 0; transform: translateX(100%); transition: transform 0.3s ease; } .mobileMenu.open { transform: translateX(0); } :global([dir="rtl"]) .mobileMenu { right: auto; left: 0; transform: translateX(-100%); } :global([dir="rtl"]) .mobileMenu.open { transform: translateX(0); }

Testing RTL

The local dev server lets you switch locales. Test with Arabic (ar) to verify your RTL layout:

npm run dev -- --template my-template --locale ar

Templates that don’t properly support RTL will be rejected during review. Test every page and component in RTL mode before submitting.

Last updated on