CSS Reference Guide

All TopicsPlayground

CSS Logical Properties

Write direction-agnostic CSS that automatically adapts to different writing modes and text directions — essential for internationalization and modern layout.

LayoutInternationalizationModern CSSRTL Support

Physical vs Logical Properties

Traditional CSS properties like margin-left and padding-right are physical — they always refer to the same side of the screen regardless of text direction. Logical properties instead reference the flow-relative direction, automatically adapting when the writing direction changes.

Physical Properties (direction-dependent)
/* Physical — always the left side, even in RTL */
.card {
  margin-left: 20px;
  padding-right: 16px;
  border-top: 2px solid #ccc;
  width: 300px;
}
Logical Properties (direction-agnostic)
/* Logical — adapts to writing direction automatically */
.card {
  margin-inline-start: 20px;
  padding-inline-end: 16px;
  border-block-start: 2px solid #ccc;
  inline-size: 300px;
}
Why Logical? If your site supports Arabic, Hebrew, or any RTL language, logical properties save you from writing separate rules for dir="rtl". The layout simply mirrors itself.

Block & Inline Axes

Logical properties revolve around two flow-relative axes:

Block & Inline Axes Visualization (LTR Horizontal)
block-start (top) block-end (bottom) inline-start (left in LTR) inline-end (right in LTR) Content Area
Axis Keywords
/* Block axis = vertical in horizontal writing modes */
margin-block-start: 1rem;   /* = margin-top    */
margin-block-end: 1rem;     /* = margin-bottom */

/* Inline axis = horizontal in LTR */
margin-inline-start: 1rem;  /* = margin-left (LTR) / margin-right (RTL) */
margin-inline-end: 1rem;    /* = margin-right (LTR) / margin-left (RTL) */

Writing Mode

The writing-mode property changes which direction is block and which is inline, which redefines how logical properties map to physical ones.

writing-mode values
.horizontal {
  writing-mode: horizontal-tb;  /* default — text left→right, blocks top→bottom */
}

.vertical-rl {
  writing-mode: vertical-rl;    /* text top→bottom, blocks right→left (Japanese) */
}

.vertical-lr {
  writing-mode: vertical-lr;    /* text top→bottom, blocks left→right (Mongolian) */
}
Writing Modes Comparison
horizontal-tb (default) This text flows left to right, lines stack top to bottom.
vertical-rl Text flows top to bottom, lines stack right to left.
vertical-lr Text flows top to bottom, lines stack left to right.

Logical Margins

Logical margin properties replace margin-top/right/bottom/left with flow-relative equivalents.

Logical Margin Properties
.element {
  /* Individual sides */
  margin-block-start: 1rem;   /* top in LTR horizontal */
  margin-block-end: 2rem;     /* bottom */
  margin-inline-start: 1rem;  /* left in LTR */
  margin-inline-end: 2rem;    /* right in LTR */

  /* Shorthand: two values = start end */
  margin-block: 1rem 2rem;     /* block-start block-end */
  margin-inline: 1rem 2rem;    /* inline-start inline-end */

  /* Single value applies to both sides */
  margin-block: 1rem;           /* top & bottom */
  margin-inline: auto;          /* horizontal centering! */
}
margin-inline: auto (centering)
margin-inline: auto

Logical Padding

Padding follows the same logical naming pattern as margins.

Logical Padding Properties
.card {
  /* Individual */
  padding-block-start: 2rem;
  padding-block-end: 2rem;
  padding-inline-start: 1.5rem;
  padding-inline-end: 1.5rem;

  /* Shorthand */
  padding-block: 2rem;        /* top & bottom */
  padding-inline: 1.5rem;     /* left & right (LTR) */
}
Asymmetric Logical Padding
padding-block: 0.5rem 2rem padding-inline: 1rem 3rem Notice the extra padding at block-end (bottom) and inline-end (right in LTR).
Same CSS, but dir="rtl" padding-inline flips! Extra padding is now at inline-end (left in RTL).

Logical Borders

Borders also have complete logical equivalents including width, style, color, and radius.

Logical Border Properties
.element {
  /* Block axis borders */
  border-block-start: 2px solid #6366f1;
  border-block-end: 1px solid #ccc;
  border-block: 1px solid #ccc;  /* both */

  /* Inline axis borders */
  border-inline-start: 4px solid #6366f1;
  border-inline-end: none;
  border-inline: 1px solid #ccc;  /* both */

  /* Logical border-radius */
  border-start-start-radius: 8px;  /* top-left in LTR */
  border-start-end-radius: 8px;    /* top-right in LTR */
  border-end-start-radius: 8px;    /* bottom-left in LTR */
  border-end-end-radius: 8px;      /* bottom-right in LTR */
}
border-inline-start accent
LTR — border-inline-start is on the left
RTL — border-inline-start is on the right

Logical Sizing

Instead of width and height, use inline-size and block-size.

Logical Sizing Properties
.box {
  /* Instead of width/height */
  inline-size: 300px;         /* = width in horizontal mode */
  block-size: 200px;          /* = height in horizontal mode */

  /* Min / Max variants */
  min-inline-size: 100px;     /* = min-width */
  max-inline-size: 600px;     /* = max-width */
  min-block-size: 50px;       /* = min-height */
  max-block-size: 400px;      /* = max-height */
}

/* Common pattern: responsive max-width replacement */
.container {
  max-inline-size: 1200px;
  margin-inline: auto;
}

Inset Shorthand

The inset property is the logical shorthand for top, right, bottom, left, and has logical axis variants.

Inset Properties
.overlay {
  position: absolute;

  /* Physical shorthand — all four sides */
  inset: 0;                       /* top:0 right:0 bottom:0 left:0 */
  inset: 10px 20px;                /* top/bottom:10px right/left:20px */
  inset: 10px 20px 30px 40px;      /* top right bottom left */

  /* Logical axis shorthands */
  inset-block: 0;                  /* block-start & block-end */
  inset-block-start: 10px;         /* = top */
  inset-block-end: 20px;           /* = bottom */

  inset-inline: 0;                 /* inline-start & inline-end */
  inset-inline-start: 10px;        /* = left (LTR) / right (RTL) */
  inset-inline-end: 20px;          /* = right (LTR) / left (RTL) */
}
inset: 0 for full-cover overlay
This is background content underneath the overlay.
position: absolute; inset: 0;

Logical Text Alignment

Use start and end instead of left and right for direction-aware alignment.

Logical text-align Values
.text-start {
  text-align: start;  /* left in LTR, right in RTL */
}

.text-end {
  text-align: end;    /* right in LTR, left in RTL */
}

/* Also works in Flexbox */
.flex-container {
  justify-content: flex-start;  /* already logical! */
}
text-align: start vs end (LTR & RTL)
LTR — text-align: start
Aligns to the left
LTR — text-align: end
Aligns to the right
RTL — text-align: start
Aligns to the right
RTL — text-align: end
Aligns to the left

Full Mapping Table: Physical → Logical

A complete reference of physical properties and their logical equivalents (in horizontal-tb + LTR).

Physical Property Logical Property Axis
margin-topmargin-block-startBlock
margin-bottommargin-block-endBlock
margin-leftmargin-inline-startInline
margin-rightmargin-inline-endInline
padding-toppadding-block-startBlock
padding-bottompadding-block-endBlock
padding-leftpadding-inline-startInline
padding-rightpadding-inline-endInline
border-topborder-block-startBlock
border-bottomborder-block-endBlock
border-leftborder-inline-startInline
border-rightborder-inline-endInline
widthinline-sizeInline
heightblock-sizeBlock
min-widthmin-inline-sizeInline
max-widthmax-inline-sizeInline
topinset-block-startBlock
bottominset-block-endBlock
leftinset-inline-startInline
rightinset-inline-endInline
text-align: lefttext-align: startInline
text-align: righttext-align: endInline
border-top-left-radiusborder-start-start-radiusBoth
border-top-right-radiusborder-start-end-radiusBoth
border-bottom-left-radiusborder-end-start-radiusBoth
border-bottom-right-radiusborder-end-end-radiusBoth

RTL Live Demo — Auto-Adaptation

This demo uses only logical properties. Toggle the direction to see the entire card layout adapt automatically — no extra CSS needed.

Card with Logical Properties (click to toggle RTL)
A

Ahmed Hassan

Senior Frontend Developer

CSS React TypeScript
"Logical properties changed how I think about layout. My RTL support went from a nightmare to zero extra effort."
Try it! Click "Switch to RTL" above. Notice how the avatar moves to the right, the quote border flips, tag padding adjusts, and text alignment changes — all without a single dir="rtl" override in CSS.

Gotchas

Don't mix physical and logical for the same axis. Using margin-left and margin-inline-start together can cause unexpected behavior. Pick one approach and stick with it.
The margin shorthand is still physical. margin: 10px 20px 30px 40px maps to top/right/bottom/left. There is no single logical shorthand that replaces the four-value margin. Use margin-block and margin-inline separately.
Logical border-radius names are confusing. border-start-start-radius means block-start + inline-start (top-left in LTR). The format is border-{block}-{inline}-radius. Take time to memorize the pattern.
Transforms and positions are still physical in some cases. transform: translateX() is always horizontal. There's no logical equivalent for transforms yet.

Pro Tips

Start adopting logical properties today. Even if you don't support RTL yet, using margin-inline and padding-block is more expressive and future-proof. Modern browsers have excellent support.
Use margin-inline: auto for centering. It's the logical equivalent of margin: 0 auto and reads more clearly — you're centering on the inline axis.
Combine with :dir() pseudo-class. For the rare cases where you need direction-specific overrides that logical properties can't solve, use :dir(rtl) instead of [dir="rtl"] — it checks the computed direction, not just the attribute.
Use stylelint-use-logical. This ESLint plugin automatically flags physical properties and suggests their logical equivalents. Great for gradual migration.
Modern Logical-First Card Component
.card {
  max-inline-size: 400px;
  margin-inline: auto;
  padding-block: 1.5rem;
  padding-inline: 2rem;
  border-block-start: 4px solid var(--accent);
  border-start-start-radius: 12px;
  border-start-end-radius: 12px;
}

.card__icon {
  margin-inline-end: 1rem;
  inline-size: 48px;
  block-size: 48px;
}

.card__meta {
  margin-block-start: 0.5rem;
  padding-inline-start: 1rem;
  border-inline-start: 2px solid var(--muted);
  text-align: start;
}
PreviousSelectors Deep Dive