Wednesday, May 13, 2026
When to reach for logical properties (and when not to)
CSS logical properties describe how content flows; physical properties describe where the box sits. A mental model for picking between them, with practical examples of both.
On this page
There's a school of thought in front-end circles: logical properties everywhere. margin-left is dead, long live margin-inline-start! Chris Coyier put it plainly in July 2025: "yes, just use logical properties all the time. If you need an answer with zero nuance, there it is." It's an entirely reasonable position with real benefits — consistency, future-proofing for i18n, fewer judgment calls in code review.
I've landed somewhere a little different personally; perhaps it's just my love of nuance. The short version: logical properties carry semantic meaning that physical properties don't, and leaning on that meaning makes CSS easier to read later. So I reach for logical properties wherever styles relate to content or content containment, and I keep physical properties for values that are anchored to the viewport, device, or hardware interaction.
Both approaches ship. Neither is wrong. This post is about why the split feels right to me and where the boundary lands in practice.
# What logical properties actually claim
When you write margin-inline-start: 1rem, you're making a small semantic claim: this margin belongs on the side where reading begins. In English (LTR), that's the left. In Arabic (RTL), that's the right. In traditional Japanese (vertical-rl), that's the top.
MDN frames it nicely: logical properties "control layout through logical rather than physical direction and dimension mappings." web.dev's framing is even more concrete: physical properties refer to viewport dimensions ("like a compass rose on a map"); logical properties refer to the edges of a box as they relate to the flow of content.
That distinction is the part I find genuinely useful; it lets the property name carry information about what the value means, not just where it lives.
# The heuristic
A metaphor that's helped me hold this in my head: content is a river, the viewport is a riverbed.
The river moves quickly, finding its way through whatever channel it's given — its direction depends on the terrain. The riverbed shapes that channel, but on a different timescale; it's eroded and reshaped over much longer stretches by the water itself. Both are in motion, but they answer to different forces and respond at different speeds.
Logical properties describe the river: values that adapt as the reader's language and writing mode shifts. Physical properties describe the riverbed: values anchored to the slower-moving facts of the device, the viewport, and the platform conventions users expect.
So before writing a directional property, I ask: does this value follow the reader, or follow the screen?
- Follows the reader (the river) → logical (
margin-inline,padding-block,border-inline-start,inset-block-end) - Follows the screen (the riverbed) → physical (
top,right,bottom,left)
That's the whole rule. The rest is examples.
# Content and content containment: a great fit for logical
This is the river. Anything wrapping prose, form fields, lists, cards, articles — anything where the box exists to hold content that flows in reading order — is where logical properties earn their keep.
A prose container
.article-body { max-inline-size: 65ch; padding-inline: 1.5rem; padding-block: 2rem; margin-inline: auto;}.article-body > * + * { margin-block-start: 1em;}.article-body blockquote { border-inline-start: 4px solid var(--color-accent); padding-inline-start: 1rem; margin-block: 1.5rem;}max-inline-size: 65ch says "the reading measure should be ~65 characters along the reading axis" — true in English, Arabic, and Japanese alike. The blockquote's accent bar stays on the side where lines start. If this site ever gets translated, the typography keeps working without retrofitting.
The same component with physical properties
.article-body { max-width: 65ch; padding: 2rem 1.5rem; margin: 0 auto;}.article-body blockquote { border-left: 4px solid var(--color-accent); padding-left: 1rem;}This renders identically in English and is fine if you're only ever shipping LTR. The trade-off shows up later: in an RTL translation the blockquote's accent bar lands on the trailing edge instead of the leading edge, which inverts the visual hierarchy. Logical properties let you skip that retrofit.
A search field
.input-search { padding-inline: 1rem 2.5rem; /* room for the search icon on the trailing edge */ padding-block: 0.5rem; border-inline-start: 3px solid var(--color-border-strong);}The icon sits on the trailing edge of the field — right in English, left in Arabic. The leading border accent stays on the side where text begins. Both flip correctly with dir="rtl" — no [dir="rtl"] overrides, no rtlcss build step. Ahmad Shadeed's RTL Styling 101 is the canonical deeper dive if you want one.
# Viewport-anchored chrome: where physical still describes what you mean
And this is the riverbed. Some styles aren't really about content flow — they're about the device, the viewport, or the user's hand on a pointer. For these, physical property names map more directly to the intent.
A back-to-top button
.back-to-top { position: fixed; bottom: 1.5rem; right: 1.5rem; inline-size: 3rem; block-size: 3rem; border-radius: 50%;}This button belongs in the bottom-right corner of the viewport, not the trailing-bottom corner of the reading direction. When someone switches their browser to Arabic, they probably don't expect the "back to top" button to migrate to the bottom-left of their screen — convention and muscle memory point to bottom-right regardless of locale.
Notice the mix: position: fixed and bottom/right describe the viewport anchor, while inline-size/block-size describe the box dimensions. That's roughly the line: the anchor is physical, the box is content-related.
The same button with logical insets
.back-to-top { position: fixed; inset-block-end: 1.5rem; inset-inline-end: 1.5rem; /* ... */}In English this is identical. In Arabic the FAB moves to the opposite corner — which might be exactly what you want for some designs, but is often surprising. This is the case Chris Coyier acknowledged in his own piece: "place this chat widget on the bottom right of the page. The language perhaps doesn't matter here." Whichever you choose, it's worth making the choice deliberately rather than letting the property name decide for you.
A draggable resize handle
.panel-resize-handle { position: absolute; top: 0; bottom: 0; right: 0; width: 4px; cursor: col-resize;}The user's pointer mechanics are physical. The handle sits on the right edge of the panel because that's where their hand expects it for a left-to-right pane layout. If the broader layout mirrors in RTL, the panel might mirror too — but that's a layout-level decision worth making explicitly.
A notification badge
.avatar { position: relative;}.avatar-badge { position: absolute; top: -2px; right: -2px; width: 12px; height: 12px; border-radius: 50%; background: var(--color-danger);}Notification badges are conventionally top-right on avatars across most platforms — iOS, Android, web. That's a visual design convention rather than a reading-flow statement, so physical property names match the intent.
Print styles
@media print { @page { margin-top: 0.75in; margin-bottom: 0.75in; margin-left: 1in; margin-right: 1in; }}Print margins map to physical paper. The binding edge of a sheet isn't a content-flow concept; it's a physical-medium concept. Logical equivalents exist on @page, but the values you're picking are usually about sheet orientation, not language.
# Where it gets fuzzy
Some cases sit on the border. Here's how I tend to resolve them — though reasonable people will land differently.
Icons inside buttons
/* Pagination "next" button — part of reading flow */.btn-next .icon-arrow { margin-inline-start: 0.5rem;}/* Mute icon on a volume slider — UI convention */.volume-control .icon-mute { margin-right: 0.5rem;}The pagination arrow is part of the reading flow — "Next →" should become "→ التالي" in Arabic. The mute icon next to a volume slider is closer to UI chrome convention than to reading order, so physical reads more naturally to me. Other devs reasonably go either way here.
Grid and flex layouts
/* Content-driven layout: sidebar holds related reading, main holds the article */.article-layout { display: grid; grid-template-columns: 1fr 16rem; gap: 2rem;}Grid and flex are already writing-mode-aware — grid-template-columns reverses automatically in RTL because the inline axis reverses. The cleanest case: use the default behavior and the layout follows content flow because grid and flex were designed that way.
If you specifically don't want a layout to reverse — say, a media-player UI where the timeline scrubber should stay LTR regardless of locale — that's when explicit physical positioning or direction: ltr on the subtree comes in.
Box dimensions
/* The image's intrinsic dimensions are physical — it's a 1200×800 photo */.hero-image { width: 100%; max-width: 1200px; height: auto; aspect-ratio: 3 / 2;}/* The card's content-defined dimensions are logical */.card { max-inline-size: 28rem; min-block-size: 12rem;}width/height for hardware-anchored or media-intrinsic dimensions; inline-size/block-size when the dimension is defined by content flow. In practice, max-inline-size on text containers and width/height on media covers most cases.
# The "logical everywhere" position, fairly stated
The strongest version of the always-logical case is worth engaging with on its own terms:
- Consistency reduces cognitive load. One rule is easier to enforce than a per-property judgment call, especially across a team.
- Future-proofing is cheap. Logical properties behave identically to physical ones in default LTR mode, so there's no rendering cost to defaulting to them.
- The boundary really is fuzzy. If teammates disagree about whether a sidebar is content-related or layout-related, you spend time on that instead of shipping.
Jens Oliver Meiert pushed back on Coyier's piece from a different direction — he argues there's no universal requirement to use logical properties, and that for English-only projects the cognitive overhead of always-logical is real.
My preference for the content-vs-chrome split is essentially this: I want the property name to carry information about what the value means. When I read inset-inline-end six months later, I want to be confident the value should follow the reading direction. When I read right, I want to be confident the value is anchored to the screen. If the codebase uses logical-everywhere, both properties communicate "directional offset" but neither communicates which kind, and I have to read the surrounding context to find out.
That's a small cost per property and a real benefit in maintainability for me. Others reasonably weigh it differently. Both shapes of codebase ship, and both can be excellent.
# The one-screen decision guide
When reviewing CSS, for each directional property I ask:
- Does this value relate to text, content, or a content container? → logical fits well
- Does this value relate to viewport position, device orientation, or hardware interaction? → physical fits well
- Would I want this to flip in RTL or vertical writing modes? → logical if yes, physical if no
- Is this a design convention anchored to a physical screen location (top-right badge, bottom-right FAB, fixed header)? → physical fits the intent
If "what does this value actually mean?" answers as "the side where reading begins," logical reads naturally. If the answer is "the bottom of the screen," physical reads naturally.
# Browser support, briefly
This used to be a real concern; it isn't anymore. CSS logical properties have been Baseline widely available since 2023, and Safari 15 closed the last meaningful gap. Adrian Roselli updated his canonical post in August 2025 to confirm the same. If you're targeting modern evergreen browsers, you can use logical properties freely — the open question is the style one, not the support one.
One small caveat: the inset shorthand accepts physical-mapped values in the order top/right/bottom/left, so even though the property name reads "logical-ish," the shorthand is physical. For logical offsets, use the individual inset-block-* / inset-inline-* properties.
# TL;DR
Logical properties describe content flow. Physical properties describe viewport position. They overlap in default LTR mode, so the choice is mostly about which one matches your intent.
- Reading containers, prose, form fields, cards, lists, content borders, content spacing → logical fits naturally
- Fixed-position chrome, viewport-anchored buttons, notification badges, drag handles, print page margins, media-intrinsic dimensions → physical fits naturally
- When fuzzy, the question I find useful: should this flip with reading direction? Yes → logical. No → physical.
Whichever convention you adopt, pick deliberately and document it. The "logical everywhere" teams ship great code. The "logical for content, physical for chrome" teams ship great code. The unhappy middle is the one where the choice is made property by property without any shared rationale.
And whichever you pick, the upside of thinking about your CSS this way is that you stop worrying about what's just around the riverbend — your styles already know how to follow the water.
# Resources
- CSS logical properties and values — MDN — the spec-aligned reference
- Logical Properties — web.dev — the "compass rose vs. content flow" framing
- CSS Logical Properties — Adrian Roselli — comprehensive cheat sheet, updated Aug 2025
- Digging Into CSS Logical Properties — Ahmad Shadeed — practical RTL-first perspective
- RTL Styling 101 — Ahmad Shadeed — the canonical reference for RTL-aware CSS
- Should we NEVER use non-logical properties? — Chris Coyier — the "logical everywhere" argument, well made
- Should We Never Use Non-Logical Properties? — Jens Oliver Meiert — the pushback
- CSS Logical Properties are cool — don't use them — beeps — older, but the spec-shorthand awkwardness it documents is still partially relevant
- From margin-left to margin-inline — Brett Dorrans — design systems framing
inset— MDN — the one shorthand that mixes physical and logical semantics