RTL & Internationalisation
Sitka is built on CSS logical properties so layouts mirror correctly in right-to-left scripts (Arabic, Hebrew, Persian) without overrides. This page covers the property mapping, audit checklist, and language detection patterns.
Why logical properties
Physical properties like margin-left are hardcoded to screen direction. Logical properties like margin-inline-start resolve relative to the writing direction set by dir or writing-mode. In LTR, inline-start is left. In RTL, it becomes right — automatically.
Physical (avoid)
.sidebar {
margin-left: 16px;
padding-left: 12px;
border-left: 1px solid …;
left: 0;
}Logical (preferred)
.sidebar {
margin-inline-start: 16px;
padding-inline-start: 12px;
border-inline-start: 1px solid …;
inset-inline-start: 0;
}Property mapping
| Physical | Logical equivalent | Notes |
|---|---|---|
| margin-left | margin-inline-start | Leading margin — left in LTR, right in RTL |
| margin-right | margin-inline-end | Trailing margin |
| padding-left | padding-inline-start | Leading padding |
| padding-right | padding-inline-end | Trailing padding |
| border-left | border-inline-start | Leading border |
| border-right | border-inline-end | Trailing border |
| left | inset-inline-start | Positioned element leading edge |
| right | inset-inline-end | Positioned element trailing edge |
| top | inset-block-start | Block start (usually top) |
| bottom | inset-block-end | Block end (usually bottom) |
| width | inline-size | Horizontal size |
| height | block-size | Vertical size |
| text-align: left | text-align: start | Align to reading start |
| text-align: right | text-align: end | Align to reading end |
| float: left | float: inline-start | Float to reading start |
Setting direction
<!-- LTR (default) -->
<html lang="en" dir="ltr">
<!-- RTL (Arabic, Hebrew, Persian) -->
<html lang="ar" dir="rtl">
<!-- Mixed content: scope to element -->
<p dir="rtl">مرحبا</p>// app/layout.tsx
export default function RootLayout({
children,
params: { locale },
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const dir = ["ar","he","fa","ur"].includes(locale)
? "rtl" : "ltr";
return (
<html lang={locale} dir={dir}>
<body>{children}</body>
</html>
);
}Audit checklist
Use this checklist when auditing an existing component for RTL support. ✓ = covered by logical properties. △ = requires manual review.
| Item | Status | Notes |
|---|---|---|
| Directional margins / padding | ✓ | Use inline-start / inline-end |
| Absolute positioning (left/right) | ✓ | Use inset-inline-start / end |
| Text alignment | ✓ | Use start / end, not left / right |
| Border radius (leading corner) | ✓ | Use border-start-start-radius etc. |
| Icons inside buttons | △ | Review icon direction (arrows, chevrons) |
| Flex row direction | △ | flex-direction: row already mirrors in RTL |
| Animations (slide from left) | △ | Use translateX with logical sign or rtl overrides |
| Custom scroll positioning | △ | scrollLeft behaves differently in RTL |
Tailwind CSS v4
Tailwind v4 ships logical property utilities natively. Use ps-4 (padding-inline-start) and pe-4 (padding-inline-end) instead of pl-4 / pr-4 for components that must work in RTL.
- →
ps-{n} / pe-{n} → padding-inline-start / end - →
ms-{n} / me-{n} → margin-inline-start / end - →
start-{n} / end-{n} → inset-inline-start / end - →
border-s / border-e → border-inline-start / end - →
rounded-s-{n} / rounded-e-{n} → leading / trailing corner radius