Logical properties and writing-mode aware UI. Physical properties like margin-left and width assume horizontal left-to-right text. Logical properties describe start, end, block, and inline edges so the same CSS works when direction or writing mode changes.
Block and inline axes
In horizontal writing (English, most European languages):
- Inline – left to right (the direction text flows)
- Block – top to bottom (lines stack vertically)
In vertical writing modes, those axes swap relative to the screen. Logical properties follow the text, not the monitor.
Common logical replacements
/* Physical to Logical */
/* margin-top/bottom to margin-block */
/* margin-left/right to margin-inline */
/* padding-top/bottom to padding-block */
/* padding-left/right to padding-inline */
/* width to inline-size */
/* height to block-size */
/* top/bottom to inset-block */
/* left/right to inset-inline */
/* border-left to border-inline-start */
/* text-align: left to text-align: start */
Shorthands exist: margin-block: 1rem 2rem is start then end; margin-inline: auto centres horizontally in LTR.
Example: a component in logical properties
.callout {
padding-block: 1rem;
padding-inline: 1.25rem;
border-inline-start: 4px solid var(--color-accent);
margin-block-end: 1.5rem;
max-inline-size: 40rem;
}
.callout__title {
margin-block: 0 0.5rem;
text-align: start;
}
The accent border sits on the ‘start’ side – left in LTR, right in RTL. No separate RTL stylesheet for this pattern.
direction and dir
Right-to-left languages use dir="rtl" on html or a section, or direction: rtl in CSS:
<html lang="ar" dir="rtl">
…
</html>
Prefer the HTML dir attribute when content direction is document-wide; CSS direction for local overrides. Logical properties then mirror automatically.
writing-mode
Vertical layouts – sidebar labels, Japanese-style headings, decorative type – use writing-mode:
.vertical-label {
writing-mode: vertical-rl;
text-orientation: mixed;
}
.sidebar-nav {
writing-mode: vertical-lr;
display: flex;
flex-direction: column;
gap: 1rem;
}
vertical-rl flows top to bottom, lines progress right to left. vertical-lr flows top to bottom, lines progress left to right. Flex and Grid follow the writing mode: ‘row’ and ‘column’ flip meaning relative to the block and inline axes.
Logical borders and radii
.tab {
border-block-end: 2px solid transparent;
border-end-end-radius: 0.25rem;
}
.tab[aria-selected="true"] {
border-block-end-color: var(--color-accent);
}
Corner radii use start-start, start-end, end-start, end-end instead of top-left and friends. Easier to get wrong on first use – check in DevTools with direction toggled.
Flexbox and Grid with logical values
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
padding-inline: 1.5rem;
padding-block: 0.75rem;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem;
}
justify-content and align-items already respect writing mode in modern browsers. Physical padding on the same component does not – that is the migration target.
Migration strategy
You do not rewrite an entire codebase overnight. Use logical properties in new components and when you touch existing rules. Symmetric vertical spacing (margin-block) and horizontal padding (padding-inline) are the highest-value swaps for LTR-only sites because they read clearly and future-proof RTL.
Keep physical properties where a design truly means ‘always the left edge’ – rare, but a full-bleed image anchored to the viewport left might be intentional.
The next tutorial covers scroll-driven effects and sticky patterns – headers that stay put, scroll snapping, and not breaking UX in the process.

