
CSS Logical Properties for Multi-Directional Layouts
When building user interfaces that support both Left-to-Right (ltr) languages like English and Right-to-Left (rtl) languages like Arabic or Hebrew, physical CSS properties (margin-left, padding-right, border-left, left) quickly become a maintenance bottleneck. Every physical horizontal offset hardcodes an assumption that text starts on the left and flows to the right, forcing teams to maintain separate [dir="rtl"] override stylesheets that reset margin-left: 0 and apply margin-right instead.
The CSS Logical Properties and Values Level 1 specification solves this by replacing physical coordinates (top, right, bottom, left) with flow-relative axes tied to the document's dir and writing-mode:
- The inline dimension runs parallel to the flow of text within a line (
inline-starttoinline-end). - The block dimension runs perpendicular to the flow of text, stacking paragraphs and blocks (
block-starttoblock-end).
Example
/* Legacy physical CSS requiring manual [dir="rtl"] overrides */
.callout-legacy {
margin-bottom: 1.5rem;
padding-left: 1rem;
border-left: 4px solid #2563eb;
}
[dir="rtl"] .callout-legacy {
padding-left: 0;
padding-right: 1rem;
border-left: 0;
border-right: 4px solid #2563eb;
}
/* Flow-relative CSS Logical Properties: flips automatically in RTL */
.callout-logical {
margin-block-end: 1.5rem;
padding-inline-start: 1rem;
border-inline-start: 4px solid #2563eb;
}
Input : UI components rendered across <html dir="ltr"> and <html dir="rtl"> locales
Output : Single-source stylesheets whose spacing, borders, and alignment mirror automatically with text direction.
Implementation
Below is a practical translation table and component stylesheet showing how physical properties map to their flow-relative logical equivalents across modern evergreen browsers (Chrome, Edge, Firefox, and Safari).
<!-- Switch dir="ltr" to dir="rtl" and the entire layout mirrors automatically -->
<section class="notification-banner" dir="rtl" lang="ar">
<div class="notification-banner__icon" aria-hidden="true">!</div>
<div class="notification-banner__content">
<h2 class="notification-banner__title">تحديث إعدادات الحساب</h2>
<p class="notification-banner__text">
تم تفعيل المصادقة الثنائية لحمايةجلستك الحالية.
</p>
</div>
<a class="notification-banner__action" href="#settings">الإعدادات</a>
</section>
.notification-banner {
display: flex;
align-items: center;
/* max-width -> max-inline-size */
max-inline-size: 42rem;
/* margin-top / margin-bottom -> margin-block */
margin-block: 1.5rem;
/* margin-left / margin-right -> margin-inline */
margin-inline: auto;
/* padding-top/bottom and padding-left/right */
padding-block: 1rem;
padding-inline: 1.25rem;
/* Accent bar always sits at the start of the reading axis */
border-inline-start: 4px solid #0ea5e9;
border-radius: 6px;
background-color: #f8fafc;
text-align: start;
}
.notification-banner__icon {
display: inline-flex;
align-items: center;
justify-content: center;
/* width / height -> inline-size / block-size */
inline-size: 2rem;
block-size: 2rem;
/* Space between the icon and text regardless of LTR or RTL */
margin-inline-end: 1rem;
border-radius: 9999px;
background-color: #e0f2fe;
color: #0369a1;
font-weight: 700;
}
.notification-banner__content {
flex: 1;
}
.notification-banner__title {
margin-block: 0 0.25rem;
font-size: 1rem;
}
.notification-banner__text {
margin-block: 0;
color: #475569;
font-size: 0.875rem;
}
.notification-banner__action {
/* Push action link to the far end of the inline axis */
margin-inline-start: 1rem;
padding-block: 0.375rem;
padding-inline: 0.75rem;
border-radius: 4px;
background-color: #0284c7;
color: #ffffff;
text-decoration: none;
font-size: 0.875rem;
}
Main Point: Default to inline-start, inline-end, block-start, and block-end properties (margin-inline-start, padding-inline, border-inline-start, text-align: start) so your components adapt to both LTR and RTL languages without duplicating selector overrides.
Credits
Photo by Ed Stone