DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

CSS Logical Properties: The Modern Way to Handle RTL, LTR, and Writing Modes

CSS logical properties replace physical directional properties (left, right, top, bottom) with logical equivalents that adapt to the document's writing direction. They're the modern approach for building interfaces that work in both left-to-right (LTR) and right-to-left (RTL) languages, as well as vertical writing modes.

The Problem with Physical Properties

Traditional CSS uses physical coordinates:

.card {
  margin-left: 16px;
  padding-right: 24px;
  border-top: 1px solid #ccc;
  text-align: left;
}
Enter fullscreen mode Exit fullscreen mode

In Arabic or Hebrew (RTL), margin-left creates space on the wrong side. You'd need to override everything:

[dir="rtl"] .card {
  margin-left: 0;
  margin-right: 16px;
  padding-right: 0;
  padding-left: 24px;
  text-align: right;
}
Enter fullscreen mode Exit fullscreen mode

Logical properties handle this automatically.

The Logical Model

Logical properties use two axes:

  • Inline: the direction text flows (left-right in English, right-left in Arabic, top-bottom in some Asian scripts)
  • Block: the direction blocks stack (top-bottom in horizontal writing, right-left or left-right in vertical)
Physical Logical
left inline-start
right inline-end
top block-start
bottom block-end

Margin, Padding, and Borders

/* Physical */
margin-left: 16px;
margin-right: 24px;
margin-top: 8px;
margin-bottom: 8px;

/* Logical equivalents */
margin-inline-start: 16px;
margin-inline-end: 24px;
margin-block-start: 8px;
margin-block-end: 8px;
Enter fullscreen mode Exit fullscreen mode

Shorthand:

/* Physical */
margin: 8px 24px 8px 16px;  /* top right bottom left */

/* Logical */
margin-block: 8px;           /* block-start and block-end */
margin-inline: 16px 24px;    /* inline-start and inline-end */
Enter fullscreen mode Exit fullscreen mode

Border:

/* Physical */
border-top: 2px solid blue;
border-left: 1px solid gray;

/* Logical */
border-block-start: 2px solid blue;
border-inline-start: 1px solid gray;
Enter fullscreen mode Exit fullscreen mode

Border radius:

/* Physical */
border-top-left-radius: 8px;
border-bottom-right-radius: 4px;

/* Logical */
border-start-start-radius: 8px;   /* block-start + inline-start */
border-end-end-radius: 4px;       /* block-end + inline-end */
Enter fullscreen mode Exit fullscreen mode

Sizing

/* Physical */
width: 300px;
height: 200px;
max-width: 600px;
min-height: 100px;

/* Logical */
inline-size: 300px;
block-size: 200px;
max-inline-size: 600px;
min-block-size: 100px;
Enter fullscreen mode Exit fullscreen mode

In horizontal writing mode, inline-size = width and block-size = height. In vertical writing mode, they swap.

Positioning

/* Physical */
.tooltip {
  position: absolute;
  top: 0;
  left: 100%;
}

/* Logical */
.tooltip {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 100%;
}
Enter fullscreen mode Exit fullscreen mode

The inset shorthand:

/* Physical */
top: 0; right: 0; bottom: 0; left: 0;  /* fills container */

/* Logical */
inset: 0;  /* same: works for all writing modes */

/* Or specific sides */
inset-block: 0;   /* top + bottom */
inset-inline: 0;  /* left + right */
Enter fullscreen mode Exit fullscreen mode

Text Alignment

/* Physical */
text-align: left;

/* Logical */
text-align: start;  /* start of inline direction */
text-align: end;    /* end of inline direction */
Enter fullscreen mode Exit fullscreen mode

start maps to left in LTR and right in RTL automatically.

Flexbox and Grid Already Use Logical Properties

Flexbox justify-content and align-items already adapt to writing-mode and direction:

.container {
  display: flex;
  justify-content: flex-start;  /* always at inline-start */
}
Enter fullscreen mode Exit fullscreen mode

This is why adding direction: rtl to a flex container automatically mirrors its children — the flex model is already logical.

Practical Example: A Card Component

Before (physical):

.card {
  padding: 16px 24px;
  margin-bottom: 16px;
  border-left: 4px solid blue;
  text-align: left;
}

[dir="rtl"] .card {
  border-left: none;
  border-right: 4px solid blue;
  text-align: right;
}
Enter fullscreen mode Exit fullscreen mode

After (logical):

.card {
  padding-block: 16px;
  padding-inline: 24px;
  margin-block-end: 16px;
  border-inline-start: 4px solid blue;
  text-align: start;
}
/* No RTL override needed */
Enter fullscreen mode Exit fullscreen mode

Browser Support

All major logical properties have excellent support in 2024:

  • margin-inline, margin-block, padding-inline, padding-block: 93%+
  • inset-inline, inset-block: 93%+
  • inline-size, block-size: 95%+
  • border-start-start-radius: 90%+

Firefox has had full logical property support since Firefox 69 (2019). There are no Firefox-specific gotchas here.

Check caniuse.com for current coverage.

Mixing Physical and Logical

You can mix them, but be careful with shorthand overrides:

.element {
  margin-inline-start: 16px;
  margin: 0;  /* This RESETS margin-inline-start! */
}
Enter fullscreen mode Exit fullscreen mode

Physical shorthands override logical properties. Use logical shorthands consistently or apply logical properties last.

When to Start Using Logical Properties

  • New projects: use logical properties from the start
  • RTL support needed: logical properties eliminate entire RTL override blocks
  • Vertical writing mode: logical properties are essentially required
  • Existing projects: migrate incrementally, one component at a time

The naming takes a moment to internalize — margin-inline-start instead of margin-left feels verbose at first. After a few days it becomes natural, and the reward is interfaces that handle RTL and other writing modes without any extra CSS.

For Firefox add-on and web extension work, logical properties ensure your extension's sidebar and popup UI adapts correctly when users have RTL system languages — no need to test-and-override each direction separately.

Top comments (0)