Web development

Logical properties for international layouts

margin-inline-start instead of margin-left: one stylesheet serves Italian, Arabic and Hebrew. The substitution map and what stays physical.

Key points

  • Logical properties follow the inline and block axes: one CSS serves both LTR and RTL.
  • box-shadow, transform and background-position stay physical: they have no logical form.
  • Mixing `margin-left` with `margin-inline-start` only shows in RTL, so test in RTL.

Logical properties replace top, bottom, left and right with the start and end of the writing axis. One stylesheet serves Italian, Arabic and Hebrew, with no second RTL version to maintain.

The substitution map

PhysicalLogicalChanges with
margin-leftmargin-inline-startText direction
margin-topmargin-block-startWriting mode
padding-bottompadding-block-endWriting mode
leftinset-inline-startText direction
widthinline-sizeText direction
border-top-left-radiusborder-start-start-radiusBoth axes

The inline axis is the one the text runs along, the block axis is the one lines wrap onto. In Italian the inline axis is horizontal, in Japanese vertical: the same logical property covers both.

A card that works in RTL

.card {
  padding-inline: 1.25rem;
  padding-block: 1rem;
  border-inline-start: 3px solid var(--accent);
  text-align: start;
}

.card__icon {
  margin-inline-end: 0.75rem;
  float: inline-start;
}

With dir="rtl" on the root element the border moves to the right and the icon swaps sides, with no extra rule. Physical properties would need a separate RTL stylesheet, or a conditional class for every side.

The test that exposes the rest

# trova le proprietà fisiche rimaste nel CSS

grep -rnE "(margin|padding)-(left|right)|inset-(left|right)|(^|[^-])left:" --include="*.css" src/

# controlla il layout con la direzione invertita
grep -rn "dir=\"rtl\"" src/

What stays physical

  • box-shadow has no logical form: the x offset stays physical and must be mirrored by hand in RTL.
  • transform: translateX() and rotation angles do not flip with direction.
  • background-position in percentages stays anchored to the physical side of the container.
  • Directional icons (arrows, chevrons, back arrows) need transform: scaleX(-1).

The record I use as an example

For directional icons the catalogue has a browsable grid: /icons, with records such as icon-search. The cards that host that content are in card, the settings panels in settings.

The EneUI catalogue indexes 12,808 icons and 1,556 blocks from 1,472 libraries (1 November 2026). Checking a mirrored icon on a real record takes less time than arguing about it in the abstract.

The known limit

The cost is not the syntax, it is the CSS you already have: a reset that sets margin-top and padding-left drags the layout back to the physical side and beats the logical class on order and specificity. In RTL the result is an inconsistent layout, with no error to flag it.

For the page structure that hosts these components see Grid with named areas. For languages and hreflang see common hreflang mistakes; the comparison between utilities and CSS Modules is in Tailwind vs CSS Modules.

Frequently asked questions

Do I have to rewrite all the existing CSS?

No. Convert first the components that must work in several languages; the rest can stay physical until an RTL market arrives.

Do they work with Flexbox and Grid?

Yes. Margins, padding, inset and inline-size work in any layout, and text-align: start replaces left without touching anything else.

Do I change lang or only dir?

Both. lang declares the language for pronunciation and hyphenation, dir declares the text direction: for Arabic and Hebrew set dir="rtl".

How do I handle icons in RTL?

Mirror only the directional ones with transform: scaleX(-1). Gears, users and non-directional symbols stay identical.

What happens in older browsers?

They ignore the logical declaration and use the previous value, if one exists. Write the physical property before the logical one when the fallback must be controlled.