skip to content

After switching a page to direction: rtl, which CSS declarations keep pointing the same physical way even when every box property has been converted to logical form?

level: seniorimportance: should knowfreq 30%

answer

  1. logical covers the box, not the decoration
  2. shadows and transforms never flip
  3. gradient and background keywords stay put
  4. flex and grid do follow direction
  5. a custom property as the flip sign

basics

~20 s

Logical properties only cover the box: margins, padding, borders, insets, sizes and corner radii. Shadows, transforms, background-position keywords, gradient directions and physical text-align values stay fixed to the screen and need a manual right-to-left pass.

solid answer

~40 s

Logical properties mirror the *box* — `margin-inline`, `padding-inline`, `border-inline-start`, `inset-inline`, `inline-size`, and the `border-start-start-radius` family — plus flow-relative values such as `text-align: start`. Everything else in CSS is still physical. `box-shadow` and `text-shadow` x-offsets, `transform: translateX()` and `rotate()`, `transform-origin: left`, `background-position: left 10px`, `linear-gradient(to right, …)`, `clip-path` coordinates and any remaining `text-align: left` all point the same way in both directions. Flex and grid are the happy exception: their inline axis follows `direction`, so a `flex-direction: row` really does reverse for `rtl` without help. In practice a right-to-left launch is a logical-property migration *plus* an audit of shadows, transforms, gradients, directional icons and third-party CSS — the last mile that a codemod cannot do for you.

code

css · 9 lines
css
:root { --flip: 1; }
:root:dir(rtl) { --flip: -1; }

.panel {
  padding-inline-start: 1rem;                      /* mirrors itself */
  box-shadow: calc(6px * var(--flip)) 0 12px #0003; /* needs the flip */
}

.chevron { transform: scaleX(var(--flip)); }

go deeper

for a junior

Know that logical properties handle margins, padding, borders and sizes, and that things like shadows and transforms are separate physical declarations you would still have to think about.

for a middle

Be able to list the non-mirroring surface concretely — shadows, transforms, background-position, gradient direction, physical radii and text-align: left — and name the flow-relative values that replace the last of those.

for a senior

Show the operating judgement: name the custom-property flip technique, know that flex and grid follow direction on their own, and insist on a visual audit in the target locale rather than a grep-based sign-off.

for a principal

Set the standard for what right-to-left support means as a commitment — which surfaces are in scope, how vendor CSS and directional assets are handled, and what gate keeps physical declarations out of new components.

## What the abstraction covers The CSS Logical Properties and Values specification re-expresses the *box model* in flow-relative terms. Everything it covers mirrors automatically when `direction` flips: - `margin-inline-start/end`, `padding-inline-start/end` - `border-inline-start` and its `-width`, `-style`, `-color` long-hands - `inset-inline-start/end` - `inline-size`, `min-inline-size`, `max-inline-size` - the logical corners `border-start-start-radius`, `border-start-end-radius`, `border-end-start-radius`, `border-end-end-radius` - flow-relative *values* like `text-align: start` and `text-align: end` Layout algorithms also honour direction on their own: in Flexbox and Grid the inline axis follows `direction`, so a row of items really does reverse for a right-to-left locale without any per-locale CSS. ## What stays stubbornly physical Everything outside the box model. These are the ones that reliably survive a "we converted everything" claim and show up as visual bugs in the right-to-left build: 1. **Shadows.** `box-shadow: 4px 0 8px rgba(0,0,0,.3)` casts to the right in both directions. So does `text-shadow`. There is no logical offset syntax. 2. **Transforms.** `transform: translateX(20px)` moves right in Arabic too. `rotate()` turns the same way, which matters for chevrons and disclosure arrows. `transform-origin: left top` is physical. 3. **Backgrounds.** `background-position: left 10px center` and the `background-position-x` longhand are physical, as are the gradient direction keywords in `linear-gradient(to right, …)` and explicit angles. 4. **Physical radii.** `border-top-left-radius` does not mirror; only the logical corner names do. 5. **Leftover physical box properties.** Anything the migration missed — including the four-value `margin`, `padding` and `inset` shorthands, which have no logical equivalent and stay in top/right/bottom/left order. 6. **Physical alignment values.** `text-align: left`, `float: left`, `clear: right` — the flow-relative values exist (`start`, `end`, `inline-start`, `inline-end`) but you have to actually use them. 7. **Masks and clipping.** `clip-path: polygon(...)` coordinates and mask positions are raw geometry with no notion of flow. 8. **Non-CSS content.** Directional artwork — back arrows, indent icons, chart glyphs — lives in markup or assets and needs its own mirroring decision. ## Why this is the real senior question Anyone can recite the property list. The judgement being probed is whether you know that logical properties get you most of the way and then stop, and that the remaining surface is exactly the decorative layer nobody writes tests for. A component can pass a mechanical audit — zero physical margins — and still render a shadow on the wrong side, a chevron pointing the wrong way, and a gradient that fades toward the wrong edge. ## How to handle the remainder **Custom properties as the flip point.** Route the physical bits through a variable and swap it once per direction: ```css :root { --dir-x: 1; } :root:dir(rtl) { --dir-x: -1; } .card { box-shadow: calc(4px * var(--dir-x)) 0 8px rgba(0, 0, 0, .3); } .chevron { transform: scaleX(var(--dir-x)); } ``` The `:dir()` pseudo-class matches an element by its resolved direction; an `[dir="rtl"]` attribute selector is the more conservative equivalent where broader support matters. **Mirror wholesale where it is safe.** `transform: scaleX(-1)` on a purely directional icon flips it correctly in one declaration — but never apply it to anything containing text or a brand mark. **Audit visually, not just mechanically.** Run the interface in a right-to-left locale and look at it. Grep can find `margin-left`; only a human notices that the elevation now reads as coming from the wrong side of the room. **Third-party CSS.** Vendor stylesheets are usually physical and out of your control. Either process them through a mirroring step or override the specific offenders in a later cascade layer. Logical box properties, including the logical corner radii, are supported across all current browsers, so the constraint here is coverage of the specification's scope — not browser support.

  • Do flex and grid layouts reverse automatically in a right-to-left document?
    Yes. Both lay items out along an inline axis that follows `direction`, so `flex-direction: row` and grid columns run right-to-left under `dir="rtl"` with no extra CSS. What does not follow is anything you pinned physically inside the items — a shadow offset, a translateX, or a physical margin the migration missed.
  • How do you flip a directional icon without shipping a second asset?
    `transform: scaleX(-1)`, applied conditionally via `:dir(rtl)` or an `[dir="rtl"]` selector, mirrors the glyph geometry. It is safe for pure arrows and chevrons and unsafe for anything containing text, numerals or a logo, which would render mirrored and unreadable.
  • What is :dir() and how does it differ from an [dir="rtl"] attribute selector?
    `:dir()` is a pseudo-class that matches on the element's *resolved* directionality, so it also matches elements that inherit their direction or get it from bidi resolution. The attribute selector only matches elements that literally carry the attribute, which means you must place it where you intend to key off it.

saying these in an interview costs you the question

  • Assumes logical properties mirror the whole stylesheet
  • Says box-shadow offsets flip with direction: rtl
  • Thinks border-top-left-radius mirrors automatically
  • Claims flex rows need manual reversal for RTL
  • Treats an RTL launch as a pure find-and-replace job

context