CSS Logical Properties
You’ve shipped a polished product. Everything looks great in English. Then a client asks: “Can we support Arabic?”
You open your stylesheet. `margin-left`. `padding-right`. `border-left`. `float: left`. `text-align: left`.
Every single one of those needs a mirror version for RTL (right-to-left) languages. Suddenly your clean CSS doubles in size with overrides wrapped in `[dir=”rtl”]` selectors. It’s a mess — and it’s entirely avoidable.
CSS Logical Properties solve this by replacing *physical* directions (left, right, top, bottom) with *logical* ones (start, end, block, inline) that adapt automatically based on writing mode and direction.
“Logical properties simplify the complexity of global web development, enabling developers to support more languages and writing modes with less effort.”
Savvy.co.il
Physical vs Logical
| Concept | Physical (old) | Logical (new) |
|---|---|---|
| Left margin | margin-left |
margin-inline-start |
| Right margin | margin-right |
margin-inline-end |
| Top padding | padding-top |
padding-block-start |
| Bottom padding | padding-bottom |
padding-block-end |
| Width | width |
inline-size |
| Height | height |
block-size |
| Top (positioned) | top |
inset-block-start |
| Left (positioned) | left |
inset-inline-start |
- `inline` = horizontal axis (left/right in LTR English, right/left in Arabic)
- `block` = vertical axis (top/bottom in horizontal writing)
Show Me the Code
Before: Physical Properties (breaks in RTL)
/* This breaks in Arabic, Hebrew, and other RTL languages */
.card {
margin-left: 24px;
padding-right: 16px;
border-left: 4px solid #275896;
text-align: left;
float: left;
}
.modal {
position: fixed;
top: 20px;
left: 0;
}
After: Logical Properties (works everywhere)
/* Works in LTR, RTL, and vertical writing modes */
.card {
margin-inline-start: 24px; /* left in LTR, right in RTL */
padding-inline-end: 16px; /* right in LTR, left in RTL */
border-inline-start: 4px solid #275896;
text-align: start; /* direction-aware */
float: inline-start; /* direction-aware */
}
.modal {
position: fixed;
inset-block-start: 20px; /* top, always */
inset-inline-start: 0; /* left in LTR, right in RTL */
}
Shorthand Properties
.element {
/* Inline axis (left + right) */
margin-inline: 24px; /* Same as: margin-inline-start + margin-inline-end */
padding-inline: 16px 32px; /* start: 16px, end: 32px */
/* Block axis (top + bottom) */
margin-block: 16px; /* Same as: margin-block-start + margin-block-end */
padding-block: 8px 24px; /* start: 8px, end: 24px */
/* Size */
inline-size: 300px; /* width */
block-size: 200px; /* height */
min-inline-size: 250px; /* min-width */
max-block-size: 400px; /* max-height */
/* Inset (positioning) */
inset: 0; /* shorthand for top/right/bottom/left */
inset-inline: 0 auto; /* left: 0, right: auto (in LTR) */
}
A Multilingual Card Component
<div class="card" dir="ltr">
<img class="card__image" src="photo.jpg" alt="Profile" />
<div class="card__content">
<h2 class="card__title">Sarah Ahmed</h2>
<p class="card__bio">Frontend Engineer</p>
</div>
</div>
<!-- Switch to RTL with one attribute change -->
<div class="card" dir="rtl">
<img class="card__image" src="photo.jpg" alt="الصورة الشخصية" />
<div class="card__content">
<h2 class="card__title">سارة أحمد</h2>
<p class="card__bio">مهندسة واجهة أمامية</p>
</div>
</div>
/* One set of styles. Works for both. */
.card {
display: flex;
gap: 16px;
padding-block: 20px;
padding-inline: 24px;
border-inline-start: 4px solid #275896;
border-radius: 8px;
}
.card__image {
inline-size: 64px;
block-size: 64px;
border-radius: 50%;
margin-inline-end: 16px; /* space after image, adapts with direction */
}
.card__title {
margin-block-end: 4px; /* space below title, always */
}
Vertical Writing Modes
.vertical-text {
writing-mode: vertical-rl; /* text flows top-to-bottom, right column first */
}
/* With logical properties, your layout still makes sense */
.vertical-text .title {
margin-block-end: 20px; /* space after text flow direction — no change needed */
padding-inline: 8px; /* padding perpendicular to text flow */
}
Browser Support & Migration Strategy
/* Progressive migration pattern */
.component {
/* Keep physical properties as fallback for very old browsers */
margin-left: 24px;
/* Logical override for modern browsers */
margin-inline-start: 24px;
}
/* In practice, if you support modern browsers only (>95% of traffic),
you can drop the physical fallback entirely */
Migration priority
- Start with new components — use logical properties from day one.
- Migrate layout-critical components (navbars, sidebars, cards) first.
- Leave decorative spacing (large hero sections) for later.
"Start using logical properties from the beginning of your project, especially if you know the website will support multiple languages or complex layouts."
For Business Leaders
Explore project snapshots or discuss custom web solutions.
The web is for everyone. If your CSS only works in one direction, your product is only for some people.
Thank You for Spending Your Valuable Time
I truly appreciate you taking the time to read blog. Your valuable time means a lot to me, and I hope you found the content insightful and engaging!
Frequently Asked Questions
No HTML changes needed. Logical properties are purely CSS. You may need to add `dir="rtl"` to your `<html>` or a container element to trigger RTL layout, but your markup structure stays the same.
`direction` controls inline (horizontal) text flow — left-to-right vs right-to-left. `writing-mode` changes the entire axis of text flow — horizontal vs vertical. Logical properties adapt to both automatically.
Yes, but be careful. Mixing them can cause unexpected results, especially when directions change. If you use `margin-left` and `margin-inline-start` on the same element, both apply and can conflict. Pick one approach per property and be consistent.
A few older properties are still catching up. `background-position` doesn't have a full logical equivalent in all browsers yet. For most layout and spacing properties however, logical equivalents exist and have excellent browser support.
Tailwind v3.3+ introduced logical property utilities like `ms-*` (margin-inline-start), `me-*` (margin-inline-end), `ps-*`, `pe-*`. If you're on Tailwind, use these classes. They work exactly the same way under the hood.
Comments are closed