Skip to lesson
Exit
Front-End Craft Deep Dive1 / 3

1 min lesson

Theming with custom properties

Talk through the example in "Theming with custom properties", then name the result it is meant to produce.

Step 1 of 3

Theming with custom propertiesdark mode and density without duplication

Define semantic tokens as CSS variables and let components consume them. Dark mode then flips a handful of values, not a parallel stylesheet. color-mix() lets you derive hover and border tints from one base color, so a palette change ripples everywhere automatically.

Semantic tokens + a derived tint; dark mode overrides only the values.
:root {
  --surface: #ffffff;
  --text: #18181b;
  --accent: #14b8a6;
  /* derive a subtle hover from the accent, no second hex to maintain */
  --accent-soft: color-mix(in oklab, var(--accent) 14%, transparent);
}
[data-theme="dark"] {
  --surface: #18181b;
  --text: #fafafa;
}
.btn { background: var(--accent-soft); color: var(--text); }
Learn more

Full explanation

Stacking contexts and z-index discipline

Stacking contexts and z-index disciplinethe bug behind every broken popover

A popover that renders behind another panel is almost never a z-index number problem - it's a stacking-context problem. transform, opacity below 1, filter and will-change all create a new stacking context, trapping a child's z-index inside its parent.

  • A z-index: 9999 child can still sit behind a sibling if its parent forms a stacking context with a lower index - z-index only competes within the same context.
  • Render overlays, menus and tooltips in a portal at the document root so they escape ancestor stacking contexts entirely.
  • Keep a small set of named layer tokens (base, dropdown, modal, toast) instead of scattering raw numbers - z-index sprawl is a maintainability smell interviewers notice.
Interview move

Say the cause before the fix: “the parent has a transform, so the popover is trapped in that stacking context and the 9999 only competes inside it. I'd portal the dropdown to the document root and replace the raw numbers with four named layer tokens.”

Learn more

Optional practice

Practice: Theming with custom properties

QA dropdown with z-index: 9999 still renders behind a neighboring panel. What's the real cause and the durable fix?