
Picture this: you’ve built a beautiful card component. Padding looks perfect in English. Then your product manager says “we need Arabic support” and suddenly everything is mirrored – your left-aligned icon is now on the wrong side, your margin-left pushes content the wrong way, and you’re drowning in [dir="rtl"] overrides that double your stylesheet size.
Or imagine a different scenario: you’re adding vertical text to a Japanese language feature. Your width and height suddenly mean the wrong thing, and your carefully tuned padding no longer aligns with the text flow. You add more hacks. The codebase grows. The confidence shrinks.
CSS Logical Properties were designed specifically to kill these problems. Rather than anchoring spacing and sizing to fixed physical directions – top, bottom, left, right – they anchor them to the flow of the document. The browser resolves which physical direction that maps to at paint time, based on writing-mode and direction. Your CSS stays lean; every language just works.
Logical properties describe positions relative to how content flows, not where it appears on screen. In English (LTR),
inline-start resolves to left. In Arabic (RTL), it resolves to right. In Japanese vertical text, it resolves to top. The same CSS declaration handles all three with zero overrides.
This isn’t experimental. Logical properties have been in the CSS specification since 2017 and have full cross-browser support in all modern browsers. The question isn’t whether to use them – it’s building the mental model so they feel as natural as margin-top.
The Two Axes
The entire system of logical properties rests on two axes. Everything – margin, padding, border, sizing, positioning – gets expressed in terms of these two axes rather than physical screen directions.
Block Axis
The block axis runs perpendicular to the direction text flows in a line. In English, text flows left to right across a line, and new lines stack downward – so the block axis runs top to bottom. block-start means “the start of the block direction,” which in English is the top. block-end is the bottom.
A useful way to think about it: block = the direction the page grows as you add more content. Paragraphs stack along the block axis. New items in a vertical list move along the block axis. Scroll (in a standard webpage) happens along the block axis.
Inline Axis
The inline axis runs parallel to the direction text flows within a line. In English (LTR), this is left to right. inline-start is the left edge where a line begins, inline-end is the right edge where it ends. In Arabic (RTL), these flip – inline-start is now on the right.
Think of it as: inline = the direction a sentence flows. Characters in a word sit along the inline axis. Words in a sentence sit along the inline axis. The inline axis is where reading direction lives.
These axes are not fixed to physical directions. They rotate and flip depending on the writing-mode and direction CSS properties. That’s the whole power of the system. The axes travel with the content flow, so your logical properties travel with them automatically – you write the CSS once, and the browser handles the geometry.
Property Explorer – click any property to highlight its edge
block-end
inline-start
inline-end
← inline →
↓ block
Shorthands as a bonus
One underappreciated benefit of logical properties is how much more expressive the shorthand forms are. padding-block: 1rem 2rem sets block-start to 1rem and block-end to 2rem in a single declaration. The physical equivalent required two separate lines: padding-top: 1rem; padding-bottom: 2rem;. These shorthands aren’t just shorter – they group related values together and signal intent more clearly. margin-inline: auto communicates “center this horizontally in the text flow direction” better than the two-property version ever did.
Physical vs. Logical: Full Reference
Here’s the complete day-to-day mapping. Notice the consistent naming formula: [property]-[axis]-[side]. Pick a property family (margin, padding, border, inset), then an axis (block or inline), then optionally a side (-start or -end). Omit the side to get the shorthand for both sides of that axis. Once you internalize that pattern, you can derive any logical property name without memorizing a list. For a broader reference on all CSS properties – including the physical counterparts listed here – see our CSS properties reference.
Spacing – Margin & Padding
| Physical | Logical Equivalent | Shorthand |
|---|---|---|
margin-top |
margin-block-start |
margin-block: [start] [end] |
margin-bottom |
margin-block-end |
– |
margin-left |
margin-inline-start |
margin-inline: [start] [end] |
margin-right |
margin-inline-end |
– |
padding-top |
padding-block-start |
padding-block |
padding-bottom |
padding-block-end |
– |
padding-left |
padding-inline-start |
padding-inline |
padding-right |
padding-inline-end |
– |
Borders
Border logical properties follow the same axis naming. Notably, border-block and border-inline let you style both edges of an axis simultaneously – something that had no physical equivalent before. Setting a consistent horizontal rule or a side-border on both left and right used to take two declarations; now it takes one.
| Physical | Logical Equivalent | Shorthand |
|---|---|---|
border-top |
border-block-start |
border-block (both edges) |
border-bottom |
border-block-end |
– |
border-left |
border-inline-start |
border-inline (both edges) |
border-right |
border-inline-end |
– |
border-top-left-radius |
border-start-start-radius |
– |
border-top-right-radius |
border-start-end-radius |
– |
border-bottom-left-radius |
border-end-start-radius |
– |
border-bottom-right-radius |
border-end-end-radius |
– |
The double-axis naming of logical border-radius (
border-start-start-radius) trips people up at first. Read it as “the corner where block-start meets inline-start.” In LTR horizontal writing, that’s the top-left corner. In RTL, it’s the top-right. It’s consistent once you see the pattern, but it’s worth committing to memory separately from the rest.
Sizing
This is where logical properties make the deepest conceptual sense. width is fundamentally the measurement along the text-flow direction – in horizontal writing that happens to be left-to-right, so width = horizontal. But in vertical writing modes like Japanese, what we’d colloquially call “width” is actually the block-axis measurement. inline-size cuts through this ambiguity: it always means “the size along the direction text flows in a line,” regardless of physical orientation.
| Physical | Logical Equivalent |
|---|---|
width |
inline-size |
height |
block-size |
min-width |
min-inline-size |
max-width |
max-inline-size |
min-height |
min-block-size |
max-height |
max-block-size |
Positioning – Inset
The inset family covers top, right, bottom, left for positioned elements. The bare inset shorthand (without an axis qualifier) is itself a new addition – it sets all four physical sides at once, like a shorthand for top + right + bottom + left. It’s not purely logical, but it’s a useful shorthand that arrived alongside the logical property work.
| Physical | Logical Equivalent | Shorthand |
|---|---|---|
top |
inset-block-start |
inset-block |
bottom |
inset-block-end |
– |
left |
inset-inline-start |
inset-inline |
right |
inset-inline-end |
– |
top + right + bottom + left |
– | inset (all 4 sides) |
The RTL Problem, Solved
Right-to-left support has historically been one of the most painful parts of internationalising a web application. The traditional approach involves writing all your CSS for LTR first, then appending a large [dir="rtl"] block that mirrors every physical property. This approach has serious maintenance problems: the RTL block doubles your spacing-related CSS, it falls out of sync with changes to the base styles, and developers who don’t work in RTL languages often forget to update it – or never test it properly.
The worst part is that this problem is entirely structural. You’re writing two sets of rules for what is conceptually one piece of information: “this element should have space on the reading-start side.” Logical properties let you express that concept once.
What the old approach looked like
/* Base LTR styles */
.nav-icon {
float: left;
margin-right: 0.75rem;
padding-left: 1rem;
border-left: 2px solid var(--brand);
}
/* RTL override block - written separately, easy to forget to update */
[dir="rtl"] .nav-icon {
float: right;
margin-right: 0;
margin-left: 0.75rem;
padding-left: 0;
padding-right: 1rem;
border-left: none;
border-right: 2px solid var(--brand);
}
The logical properties approach
/* One rule set. Handles LTR and RTL. No override needed. */
.nav-icon {
float: inline-start; /* float also accepts logical values */
margin-inline-end: 0.75rem; /* space after the icon in reading direction */
padding-inline-start: 1rem; /* breathing room on the reading-start side */
border-inline-start: 2px solid var(--brand);
}
Direction Toggle – physical vs. logical in action
margin-left · border-left · padding-left
margin-inline-start · border-inline-start · padding-inline-start
text-align and float also have logical values
It’s not just spacing properties. text-align accepts start and end as values. Using text-align: start instead of text-align: left means text aligns to the correct reading edge in both LTR and RTL without any override – and it reads more semantically accurately too. float: inline-start and float: inline-end work the same way. Even resize: block and resize: inline are available for <textarea> elements, constraining resizing to a specific axis.
/* text-align with logical values */
p { text-align: start; } /* left in LTR, right in RTL */
.label { text-align: end; } /* right in LTR, left in RTL */
.hero { text-align: center; } /* center is already direction-agnostic */
/* float with logical values */
.pull-quote { float: inline-end; } /* right in LTR, left in RTL */
Writing Modes & Vertical Text
RTL is the more common internationalisation challenge for Western developers, but logical properties shine just as brightly in vertical writing systems. Japanese, Chinese, and Korean content is frequently laid out with writing-mode: vertical-rl, where text flows from top to bottom and columns progress right to left – used in traditional literature, newspapers, and many modern Japanese UI designs. Mongolian traditionally uses writing-mode: vertical-lr, where columns progress left to right instead.
In a vertical writing mode, the axes literally rotate. The block axis now runs horizontally – because that’s the direction new columns stack. The inline axis runs vertically – because that’s the direction text flows within a column. If you’ve used physical properties throughout your CSS, you’d need to completely rethink your spacing for any vertical-mode component. With logical properties, the rotation is handled automatically by the browser – your padding-inline gives space in the vertical direction when the writing mode is vertical, exactly as it should.
Writing Modes – how the axes shift
Click a writing mode to see how the block/inline axes map →
A concrete vertical text example
Say you’re building a Japanese article layout with a sidebar label that uses writing-mode: vertical-rl. With physical properties, you’d set padding-left and padding-right for breathing room. But in vertical writing, “left” and “right” are the block axis – they control the depth of columns, not the spacing of text within a line. Your padding is suddenly applied in the wrong dimension. With logical properties, padding-inline always gives space in the text-flow direction, regardless of what physical direction that currently maps to.
.sidebar-label {
writing-mode: vertical-rl;
/* ❌ Physical - applies space in the block direction (horizontal), not inline */
padding-left: 1rem;
padding-right: 1rem;
/* ✅ Logical - always gives space in the text-flow direction */
padding-inline: 1rem; /* = top + bottom in vertical-rl */
padding-block: 0.5rem; /* = left + right in vertical-rl */
}
Live Playground
The best way to build intuition for logical properties is to manipulate them and watch the box model update in real time. Use the sliders below to adjust padding, border, and margin on different logical axes. Notice how the generated CSS uses shorthands where values are equal – the same way you’d write it in production.
Logical Box Model Builder
16px
16px
24px
24px
3px
0px
Practical Example: A Real Card Component
Theory is useful, but let’s build something real. Here’s a notification card component – the kind you’d find in a design system – written entirely with logical properties. It renders correctly in LTR, RTL, and vertical writing modes with zero additional CSS.
.notification-card {
/* Sizing: inline-size instead of width */
inline-size: 100%;
max-inline-size: 420px;
/* Padding: block for vertical rhythm, inline for horizontal breathing room */
padding-block: 1.25rem;
padding-inline: 1.5rem;
/* Accent border on the reading-start edge */
border-inline-start: 4px solid var(--brand);
/* Round only the end-side corners (the side without the accent border) */
border-start-end-radius: 8px;
border-end-end-radius: 8px;
position: relative;
}
.notification-card__icon {
/* Space between icon and text, on the end side of the icon */
margin-inline-end: 0.75rem;
}
.notification-card__badge {
position: absolute;
/* Top-right corner in LTR, top-left in RTL - no override needed */
inset-block-start: 0.75rem;
inset-inline-end: 0.75rem;
}
.notification-card__timestamp {
display: block;
margin-block-start: 0.5rem; /* space above, below the body text */
text-align: end; /* flush with reading-end edge */
}
The centering pattern to retire immediately
The single most impactful quick win in any codebase is replacing the centering pattern. How many times have you written margin-left: auto; margin-right: auto? Two lines, both required, physically anchored. Replace both with margin-inline: auto. It’s shorter, works in any writing mode, and clearly signals intent: “distribute available inline space equally on both sides.”
/* Old way - two properties, physically named */
.centered {
margin-left: auto;
margin-right: auto;
}
/* New way - one property, direction-agnostic */
.centered {
margin-inline: auto;
}
The border-radius corner naming
Logical border-radius names use a double-axis convention that takes a moment to learn. border-start-start-radius names the corner where block-start meets inline-start – in English, that’s the top-left. border-start-end-radius is where block-start meets inline-end – the top-right in LTR. It’s verbose, but it’s completely consistent with the rest of the system, and it means a “tab” UI component (rounded on two adjacent corners) automatically mirrors itself in RTL.
Migrating an Existing Codebase
You don’t need to rewrite your entire stylesheet in one sitting. The best strategy is incremental: adopt logical properties as you touch existing code, write all new code with logical properties by default, and use tooling to enforce the convention going forward. Here’s how to do each step without disrupting production.
Step 1 – Start with symmetric patterns
The safest starting point is any property that’s currently set symmetrically – same value on both left and right, or both top and bottom. These migrations are trivially correct and visually identical in LTR. If you’d rather not do it by hand, our CSS logical property converter can translate physical properties to their logical equivalents automatically:
margin-right: auto;
padding-bottom: 1rem;
padding-right: 1.5rem;
max-width: 800px;
max-inline-size: 800px;
Step 2 – Think about directional intent
Not every physical property should become a logical one. Before converting, ask: “Should this direction flip in an RTL or vertical layout?” A decorative swoosh that is always pinned to the left side of the viewport as a visual brand element? That should stay as left: 0. A “back to top” button that is always in the bottom-right regardless of language? Keep right: 1rem; bottom: 1rem. The rule is simple: physical properties for physical design decisions, logical properties for flow-relative ones.
A notification tray that is always on the right side of the screen in your product design should use
right: 0, not inset-inline-end: 0. Using the logical version would move it to the left side in RTL – which would violate the intended layout. Use logical properties where direction follows content, not where direction is a fixed product decision.
Step 3 – Update your design tokens
If you’re using CSS custom properties or a design token system, this is a good moment to audit your token names. Tokens named --spacing-left-sm encode physical direction into the token name itself. Renaming to --spacing-inline-start-sm – or more practically, restructuring so the “which side” decision happens in the component rather than the token – aligns your token architecture with logical thinking from the start.
Browser Support
Logical properties are not experimental or behind flags. They’ve been shipping in stable browsers since 2017–2020 depending on the property group, and as of 2025 they have near-universal support across all evergreen browsers. The table below reflects stable release support.
| Property Group | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| margin / padding logical | ✓ 69+ | ✓ 41+ | ✓ 12.1+ | ✓ 79+ |
| border logical | ✓ 87+ | ✓ 41+ | ✓ 15+ | ✓ 87+ |
| border-radius logical | ✓ 89+ | ✓ 66+ | ✓ 15+ | ✓ 89+ |
| inset logical | ✓ 87+ | ✓ 63+ | ✓ 14.1+ | ✓ 87+ |
| inline-size / block-size | ✓ 57+ | ✓ 41+ | ✓ 12.1+ | ✓ 79+ |
| text-align: start / end | ✓ All | ✓ All | ✓ All | ✓ All |
| float: inline-start / end | ✓ 118+ | ✓ 55+ | ✓ 15+ | ✓ 118+ |
Internet Explorer has no support and reached end-of-life in June 2022. If you’re still required to support IE, logical properties need physical fallbacks – but if you’re free of that constraint, you can use logical properties without any fallback in modern browsers. For teams that need to support Safari 12–14 specifically (the gap years for some property groups), physical property fallbacks written above the logical declaration will cascade correctly:
/* Safe pattern for wider support where needed */
.element {
margin-left: 1.5rem; /* fallback for older browsers */
margin-inline-start: 1.5rem; /* overrides in supporting browsers */
}
When Should You Use Them?
For any CSS written today, logical properties should be the default. The support is there, the DX is better (shorthands reduce line count, names signal intent more clearly), and the resilience to internationalisation changes is built in from the start. The honest question isn’t whether to use them – it’s how to make them feel as natural as the physical properties you’ve been writing for years.
Default to logical properties for…
- All spacing that should flip in RTL layouts (margin, padding, border)
- Sizing that should adapt to writing-mode changes (use inline-size, block-size)
- Any new component in a design system
- Positioning UI elements relative to text flow (icons, badges, timestamps, carets)
- Centering elements horizontally –
margin-inline: autois strictly better - Text alignment where reading direction should determine the edge
Keep physical properties for…
- Elements intentionally anchored to a fixed screen edge (viewport overlays, fixed sidebars always on the right)
- Physical canvas, SVG, or WebGL coordinates where logical properties don’t apply
- Explicit design decisions that should not mirror (brand-specific decorative layouts)
Ask: “Should this spacing or position flip if the user switches to Arabic or Japanese vertical text?” If yes, or if you’re unsure – use a logical property. Physical properties are for deliberate, direction-fixed design decisions. When in doubt, go logical.
TL;DR
CSS Logical Properties replace physical directions (top, left, right, bottom) with flow-relative equivalents (block-start, inline-start, etc.) that automatically adapt to any writing direction or mode. They eliminate RTL override blocks, make vertical-text layouts correct by default, and produce shorter, more semantically accurate CSS in the process. Browser support is universal across all modern browsers. Migration is safe and incremental. Tooling – Tailwind, ESLint plugins, CSS-in-JS – all support them without friction.
The next time you reach for padding-left, pause and ask if padding-inline-start better describes your intent. Nine times out of ten, it does.
