skip to content

For a product adding an Arabic locale, how would you choose between refactoring the stylesheet to CSS logical properties and generating a mirrored stylesheet with a build-time RTL post-processor such as rtlcss or CSSJanus?

level: principalimportance: should knowfreq 20%

answer

  1. build time versus style-resolution time
  2. one bundle or two
  3. mixed-direction pages settle it
  4. codemod cost against zero refactor
  5. neither one fixes shadows and icons

basics

~20 s

Logical properties resolve per element at style time and need one stylesheet, but require touching every rule. A post-processor flips physical declarations at build time with no refactor, yet ships two bundles and cannot handle both directions on one page.

solid answer

~50 s

The two approaches differ in *when* the mirroring happens. A post-processor like rtlcss or CSSJanus rewrites physical declarations at build time, producing a second stylesheet you serve to right-to-left locales — no source changes, works on legacy and third-party CSS, and it ships today. Its costs are structural: two bundles and a serving decision, one direction per document so a mixed-direction page is impossible, escape hatches like rtlcss's `/*rtl:ignore*/` control comments scattered through the source, and nothing for vertical writing modes. Logical properties move the decision to style resolution in the browser: one stylesheet, correct per subtree so an Arabic quote inside an English page just works, and no build coupling — at the cost of a codemod across every rule and no help for CSS you do not own. My default is logical properties as the standard for owned code, a post-processor confined to vendor stylesheets, and a visual audit either way for shadows, transforms, gradients and directional icons, which neither approach mirrors.

go deeper

for a junior

Know that both routes exist: rewrite the CSS in logical properties, or run a tool that generates a mirrored stylesheet. Being able to name the two options is enough here.

for a middle

Explain the mechanism of each — a build step rewriting physical values versus the browser resolving flow-relative ones live — and note that a post-processor produces a second bundle.

for a senior

Argue the tradeoff with concrete failure modes: mixed-direction content, escape-hatch comments accumulating in source, third-party CSS, and the residue of shadows and transforms that neither approach mirrors.

for a principal

Own the decision framework and the rollout: which inputs decide it, how the migration is sequenced by cascade layer, what lint gate prevents regression, how vendor CSS is contained, and what QA budget the launch carries.

## Frame the choice correctly This is not a question about which tool is better. It is a question about *when* the physical mapping is decided: - **Post-processor**: decided at **build time**. The output is two stylesheets whose physical values are already mirrored. - **Logical properties**: decided at **style-resolution time** in the browser, from the element's inherited `writing-mode` and `direction`. Every difference below falls out of that one distinction. ## What a post-processor gives you rtlcss and CSSJanus parse your CSS and swap physical values: `margin-left` becomes `margin-right`, `left: 0` becomes `right: 0`, `text-align: left` becomes `right`, background positions and shadow offsets are negated. Both tools have been used in production for years. **Strengths** - **No source refactor.** The existing stylesheet, however large, ships as-is. - **It handles CSS you do not own.** Vendor and third-party stylesheets go through the same pipeline. - **It flips more than the box.** Good post-processors also mirror shadow and background offsets, which logical properties do not touch at all. **Costs** - **Two artifacts.** A second bundle per direction, a serving or bundling decision, and doubled cache entries. - **One direction per document.** The whole page gets one stylesheet. A page that must render an English UI around an Arabic body, or a comment thread with mixed-direction posts, cannot be expressed. - **Escape hatches leak into source.** Anything that must *not* flip — a code block, a phone-number field, a logo — needs a control comment such as rtlcss's `/*rtl:ignore*/`. Those accumulate, and a developer who does not know the pipeline exists will not add them. - **It is a heuristic.** The tool guesses intent from syntax. Shorthands, `calc()` expressions, custom-property values and gradients are where the guesses go wrong. - **Nothing for vertical writing modes.** It only knows left/right. ## What logical properties give you **Strengths** - **One stylesheet.** No second build artifact, no serving logic, no cache split. - **Per-subtree correctness.** Because `direction` is inherited and resolved live, a right-to-left island inside a left-to-right page is automatically correct. For any product with user-generated content this is often decisive rather than merely nice. - **Intent is in the source.** `padding-inline-start` says "the gutter before the text", which is what the designer meant. The next developer inherits the meaning, not a build-time transformation they must know about. - **It generalises.** The same code is correct in vertical writing modes. **Costs** - **A codemod across the codebase**, plus review of the cases a codemod cannot decide — a physical `left` that is genuinely physical, such as a decorative element pinned to the screen edge. - **Half-migration is a real hazard.** Mixing spellings for the same side makes the outcome depend on source order. - **Third-party CSS is untouched.** You still need an answer for it. - **It covers the box only.** Shadows, transforms, gradients and directional icons remain your problem. ## The decision inputs I would actually weigh 1. **Does one page ever need both directions?** If yes, the post-processor is disqualified for owned code and the question is settled. 2. **How much CSS do we own?** A codebase that is mostly vendor CSS gets little from a refactor. 3. **Is this a one-off locale launch or a long-term internationalisation posture?** A single launch under deadline can justify the build-time route; a product committed to many locales pays the refactor once and stops thinking about it. 4. **What is the state of the design system?** If components are already tokenised, a codemod is cheap and the blast radius is contained. 5. **Is vertical typography plausible?** If Japanese vertical layout is on any roadmap, only logical properties survive it. ## The answer I would give Adopt logical properties as the standard for code we own, enforced by a lint rule so new components cannot regress, and migrate cascade layer by cascade layer — reset and base first — rather than component by component, so override order never sits in a half-migrated state. Keep a post-processor scoped to vendor stylesheets we cannot change. Then, regardless of route, budget a visual QA pass in the target locale, because the residue — shadow direction, chevron rotation, gradient angle, directional artwork — is invisible to both mechanisms and is exactly what a native reader notices first. Logical box properties are supported in all current browsers, so browser support is not a live factor in this decision; the tradeoff is entirely about migration cost, mixed-direction pages, and what each approach leaves behind.

  • Which single requirement most often decides this outright?
    Whether one page must render both directions at once. A post-processor picks a direction per stylesheet, so a page containing a right-to-left quote inside a left-to-right interface — or any user-generated content feed — cannot be served correctly by it. Logical properties resolve per element, so mixed-direction content is simply correct.
  • If you choose the logical-properties route, what stops the codebase drifting back?
    A lint rule that fails the build on physical box longhands in owned stylesheets, plus migrating whole cascade layers rather than individual components so override order is never half-converted. Convention alone does not hold; the collision between a physical and a logical declaration for the same side is decided by source order, which reviewers do not reliably catch.
  • Can the two approaches coexist?
    Yes, and that is usually the pragmatic answer. Owned code uses logical properties; vendor stylesheets you cannot edit go through a mirroring step and sit in an earlier cascade layer so your own declarations still win. The one thing to avoid is running a post-processor over logical CSS, where its physical heuristics have nothing correct to do.

saying these in an interview costs you the question

  • Treats the choice as purely a matter of taste
  • Ignores that a post-processor ships two stylesheets
  • Assumes a build-time flip handles mixed-direction pages
  • Claims either approach removes the need for visual QA
  • Cites browser support as the deciding factor today

context