Logical Properties, Modern CSS, and Performance Hints
A grab-bag of modern CSS that comes up at senior level: logical properties (margin-inline, inset-block-start) that adapt to writing direction (RTL/vertical) for free; aspect-ratio to reserve space (CLS); scroll-snap for carousels; and the performance levers — content-visibility (skip rendering offscreen content), contain (isolate a subtree), and will-change (promote to a layer, used sparingly). Plus the two preference-driven features every senior wires up: dark mode (prefers-color-scheme + color-scheme) and prefers-reduced-motion.
What are logical properties and why use them?
Flow-relative equivalents of physical properties — they follow the writing direction instead of fixed sides:
| Physical | Logical |
|---|---|
margin-left/right |
margin-inline-start/end (or margin-inline) |
margin-top/bottom |
margin-block-start/end (or margin-block) |
top/left (inset) |
inset-block-start / inset-inline-start |
width/height |
inline-size / block-size |
border-top-left-radius |
border-start-start-radius |
In an RTL locale, margin-inline-start automatically becomes the right side — so one stylesheet works for LTR and RTL without flipping. Essential for internationalized apps; good default even for LTR-only.
What does aspect-ratio do?
Sizes a box to a ratio so space is reserved before content loads — preventing layout shift (CLS):
.video { aspect-ratio: 16 / 9; width: 100%; } /* height derived; no jump when the iframe loads */
img { aspect-ratio: 3 / 2; width: 100%; height: auto; }Pair with width/height attributes on <img> for the best result (Responsive Images — srcset, sizes, <picture>).
How does scroll-snap work?
Declarative snapping for carousels/galleries — no JS:
.carousel { scroll-snap-type: x mandatory; overflow-x: auto; display: flex; }
.slide { scroll-snap-align: start; flex: 0 0 100%; }mandatory always snaps; proximity snaps only when close. scroll-driven animations (animation-timeline: view()/scroll()) extend this to tie animation progress to scroll position, also without JS.
What are content-visibility and contain?
Performance hints that limit how much the browser renders:
content-visibility: auto— skips rendering (layout/paint) of offscreen elements until they’re near the viewport, withcontain-intrinsic-sizeto reserve approximate space. Massive win for long lists/articles — the browser does layout only for what’s visible..post { content-visibility: auto; contain-intrinsic-size: auto 500px; }contain: layout/paint/size/style— promises the browser a subtree is independent, so changes inside don’t reflow/repaint the rest.contain: contentis a common bundle. Reduces the scope of layout work.
Both improve rendering performance on large pages — see Frontend Performance — Senior Interview Prep.
When should you use will-change?
Sparingly. will-change: transform hints the browser to promote an element to its own compositor layer before an animation, avoiding a first-frame jank. But it costs memory, creates a stacking context, and overuse (or leaving it on permanently) hurts performance. Apply it just before animating and remove it after; never put will-change on many elements “to be safe.” Prefer animating only transform/opacity (compositor-only, no layout/paint).
How do you implement dark mode in modern CSS?
CSS variables + prefers-color-scheme, with color-scheme so form controls/scrollbars adapt too:
:root { color-scheme: light dark; --bg: white; --fg: #111; }
@media (prefers-color-scheme: dark) { :root { --bg: #0b0b0b; --fg: #f5f5f5; } }
[data-theme="dark"] { --bg: #0b0b0b; --fg: #f5f5f5; } /* explicit override */
body { background: var(--bg); color: var(--fg); }Default from the OS preference, allow an explicit toggle to override, and set color-scheme so native UI (inputs, scrollbars) matches. Token details: Design Tokens and Theming at Scale.
What is prefers-reduced-motion and why honor it?
A media query for users who’ve asked the OS to reduce motion (vestibular disorders, distraction). Gate non-essential animation behind it (WCAG 2.3.3):
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}Reduce or remove large transforms/parallax; keep essential motion subtle.
Gotchas
content-visibility: autowithoutcontain-intrinsic-sizemakes the scrollbar jump as elements render — always provide an intrinsic size estimate.will-changeleft on permanently is a known anti-pattern — wastes memory and can reduce performance; add/remove around the animation.- Animating
width/height/top/lefttriggers layout every frame (jank); animatetransform/opacityinstead. - Mixing logical and physical properties for the same side can conflict; commit to logical for i18n.
- Dark mode flash (FOUC) — set the theme before first paint via an inline script; don’t wait for React hydration (Rendering Modes — Senior Interview Prep).
aspect-ratiowith explicit height — if both are set and conflict, height wins and the ratio is ignored; let one dimension be derived.
Related
Further reading
- MDN — CSS logical properties: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values
- MDN —
content-visibility: https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility - web.dev —
content-visibility: https://web.dev/articles/content-visibility - MDN —
prefers-reduced-motion: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
Interview angle 5
- “How do you support RTL without a second stylesheet?” - logical
properties.
margin-inline-startandinset-block-startare defined relative to the writing direction, so the same rules flip automatically. Physicalleft/rightis what forces the duplicate stylesheet. - “A long page scrolls badly. What can CSS do?” -
content-visibility: autoskips layout, paint and style for offscreen subtrees, which is usually the largest single win. Pair it withcontain-intrinsic-sizeso the skipped content still reserves height, or the scrollbar jumps as sections come into view. - “Which properties are cheap to animate, and why?” -
transformandopacity, because they can be handled by the compositor without layout or paint. Animatingwidth,topormarginre-runs layout every frame, which is what drops frames on a mid-range phone.- Follow-up: “Does
will-changemake things faster?” - only as a temporary hint before an animation starts. Left on permanently it promotes elements to their own layers, costs memory, and can make the page slower - which is the opposite of what people add it for.
- Follow-up: “Does
- “How do you implement dark mode without a flash?” - CSS custom properties
for the palette,
prefers-color-schemefor the default,color-schemeso form controls and scrollbars follow, and a tiny synchronous script before first paint to apply a stored preference. The flash is always a stored preference applied too late. - “What is the accessibility rule people forget?” -
prefers-reduced-motion. Large transitions and parallax cause genuine nausea for some users, and honouring the query is one media block rather than a redesign.