skip to content

Theming Strategy

A theme remaps semantic token values per brand, color mode or density, applied at build time or runtime, globally or to a subtree. Interviewers probe where naive theming falls apart.

part ofDesign systems & UX foundationsoverview, primer and where to startread it →
on this pageshow

explore

questions

18

In a design system, why should dark mode remap semantic token values instead of adding dark-specific styles to every component?

level: juniorimportance: must knowfreq 60%

answer

  1. components know names, not colors
  2. a mode is another value set
  3. one mapping, every component
  4. N components times M modes
  5. high contrast is just one more

basics

~20 s

Components reference semantic names such as surface, primary text and border, and a mode supplies different values for those names. One mapping switches every component at once, while per-component dark styles multiply the work and drift apart.

solid answer

~40 s

In a recruiting app, the candidate card, pipeline column and stage chip reference **semantic tokens** like `surface.default`, `text.primary`, `border.subtle` and `status.rejected.surface`, never raw colors. A **mode** is a second value set for the same names: in dark mode `surface.default` resolves to a dark grey and `text.primary` to near-white. Flip the dark-mode toggle and every component changes at once, and a component built next month is dark-ready by default. Writing dark styles into each component instead means every component needs dark work, new components forget it, the same dark surface gets three slightly different values, and the effort grows with components times modes. A high-contrast mode then becomes one more value set rather than another pass over the library — although every mode still has to be verified.

go deeper

for a junior

Recall that components reference semantic roles such as surface and primary text, and that a mode is another set of values for those same roles.

for a middle

Explain why remapping scales where per-component dark styles do not, and what the remap leaves unsolved: images, shadows, uploaded content and verification.

for a senior

Show how you would guarantee that every semantic token has a value in every mode and that status meanings and contrast hold in each one.

for a principal

Weigh how many modes the system should support, since each one adds a full value set to design, check and maintain.

## Modes are value sets, not restyles A **design token** is a named design decision; a **semantic token** names a *role* — the default surface, the primary text, a subtle border, the surface of a rejected-candidate chip — rather than a specific color. In a recruiting app's applicant-tracking screens, components reference only those roles: - the **candidate card** uses `surface.raised`, `text.primary`, `text.secondary` and `border.subtle`; - the **pipeline column** uses `surface.sunken` for its background; - the **stage chip** uses a `status.*` surface and text pair for applied, interviewing, offer and rejected. A **mode** — light, dark, high contrast — is a separate **value set** for those same names. The components never change; the mapping underneath them does. The draft Design Tokens Community Group format does not itself define modes, so systems commonly express each mode as its own set of values keyed by the same token names. ## What the remap looks like | Semantic token | Light mode | Dark mode | High-contrast light | |---|---|---|---| | `surface.default` | White | Very dark grey | White | | `surface.raised` | White with a soft shadow | A lighter grey than the default surface | White with a strong border | | `text.primary` | Near-black | Near-white | Black | | `border.subtle` | Light grey | Mid grey | Dark grey | | `status.rejected.text` | Dark red | Light red | Very dark red | Notice that the mapping is not a mechanical inversion: a raised surface in dark mode is usually *lighter* rather than shadowed, and status colors shift so they still read against the new surface. Designing those values is palette work; the design-system decision is that the values live in the mapping, not in components. ## Why per-component dark styles fail - **Work multiplies.** Every one of forty components needs a dark variant, and a third mode means another forty. - **New components forget.** The interview-scheduling panel shipped last sprint has no dark styles, so it renders as a bright white block in a dark app. - **Values drift.** Three teams choose three slightly different dark greys for what should be the same surface. - **Fixes scatter.** A contrast fix for dark text must be found and applied in every component instead of once in the mapping. ## What the remap does not solve by itself - **Images and illustrations.** An empty-pipeline illustration drawn for white backgrounds may need a dark version or a transparent background. - **Logos and uploaded content.** A candidate's uploaded résumé preview or a client company's logo arrives with its own colors. - **Shadows and elevation.** Shadows barely show on dark surfaces, so elevation needs its own mode-aware values. - **Verification.** A remap makes a component dark-*ready*, not dark-*correct*; each mode's color pairs still need contrast checks. ## Making it work in practice 1. Give components access to **semantic names only**, so nothing can bypass the mapping. 2. Define **every mode for every semantic token** — a token missing from the dark set silently shows its light value. 3. Keep **status meanings stable across modes**: rejected still reads as rejected, with contrast rechecked against the new surface — under WCAG 2.2 Level AA, 4.5:1 for normal text and 3:1 for component and state indicators. 4. Treat a new mode as **a new value set plus verification**, never as a pass over the component library. In an interview, the short version is: components bind to roles, modes remap roles to values, and that turns a per-component chore into one mapping per mode.

  • What happens if the dark value set is missing a mapping for one semantic token?
    Components using that token keep resolving to its light value, so a pale surface or dark text appears inside an otherwise dark screen, often with unreadable contrast. It fails silently rather than breaking a build. A build check that every semantic token has a value in every mode catches it before release.
  • Why is a dark mode not simply an inversion of the light colors?
    Inversion gets relationships wrong: raised surfaces in dark mode are usually lighter rather than shadowed, saturated brand and status colors glare on dark backgrounds and need adjusted values, and pure black and white create harsh contrast. The mapping is designed per role and rechecked for contrast in each mode, which is why modes are a value-set design task rather than a formula.

It is like a theatre that relights the same stage set for a night scene. The furniture and the actors' blocking stay exactly where they are; only the lighting plot changes, and one plot relights everything on stage at once.

saying these in an interview costs you the question

  • Dark mode means giving each component its own dark-specific styles.
  • A dark palette can be generated by inverting every light color.
  • Once tokens are remapped, no mode needs its own contrast checks.
  • Components should reference raw color values and let the mode swap them.
  • Adding a high-contrast mode requires rewriting every component again.
open as a page

In a design system, what are the trade-offs between applying a theme at build time and switching it at runtime?

level: middleimportance: must knowfreq 52%

basics

~20 s

Build-time theming bakes each theme's values into its own output: simple and fast, but switching means loading another output. Runtime theming resolves values while the app runs, allowing instant switching and nested scopes, at the cost of indirection and startup work.

open as a page

In a recruiting app with a dark-mode toggle, how should the in-app choice relate to the operating system's appearance preference?

level: middleimportance: must knowfreq 50%

basics

~20 s

Default to following the operating system's appearance preference, and offer three choices: system, light and dark. An explicit choice overrides the preference; system keeps tracking it live. Contrast settings are a separate axis that combines with either mode.

open as a page

In a design system with compact and comfortable density modes, what may a density switch change, and what must stay fixed?

level: middleimportance: must knowfreq 55%

basics

~20 s

A density switch may tighten padding, gaps, row and control heights, and occasionally secondary text. Pointer targets must still meet WCAG 2.2 criterion 2.5.8 (24 by 24 CSS pixels or enough spacing), and legible text, focus indicators, contrast and content stay.

open as a page

In design-system theming, how does supporting white-label clients differ from supporting a company's own several brands, and what does that change?

level: middleimportance: must knowfreq 45%

basics

~20 s

Multi-brand serves a known set of brands your own designers curate; white-label serves clients who bring their own branding, unknown in advance. White-label therefore needs a narrow override surface, derived values and automatic validation instead of hand review.

open as a page

After dark mode shipped in a recruiting app, the rejected-stage chip failed contrast only in dark. How would you keep every mode tested across the component library?

level: seniorimportance: must knowfreq 42%

basics

~20 s

Declare every foreground-background pair as data and compute its contrast in every mode on each build, failing below threshold. Add visual tests of components in each mode and key state, and make every mode part of review and release readiness.

open as a page

In a multi-brand design system, how do you decide which tokens a brand may override and which stay locked, and how do you enforce that?

level: seniorimportance: must knowfreq 40%

basics

~20 s

Let brands override what expresses identity — brand colors, typeface, radius, imagery — constrain status colors with validation, and lock what carries function or accessibility. Enforce it with a value-set schema that rejects locked keys plus automated contrast checks per brand.

open as a page

When a design-system-based app remembers a player's chosen theme, what should it store, and where, so the choice survives restarts and devices?

level: juniorimportance: should knowfreq 38%

basics

~20 s

Store a stable theme identifier, not resolved values, locally for instant startup and on the account for other devices. On load, validate the identifier and fall back to the default if the theme no longer exists.

open as a page

In a design system, why should a team needing a denser data-usage table apply the compact density mode rather than override padding locally?

level: juniorimportance: should knowfreq 40%

basics

~20 s

The compact mode tightens padding, rows and control heights across every component together, keeps the accessibility floors the system already verified, and follows future system fixes. A local override drifts from its neighbours, skips those checks and hides the gap from the system team.

open as a page

In a design system serving several brands, what should a brand theme change, and what should stay shared across every brand?

level: juniorimportance: should knowfreq 45%

basics

~20 s

A brand theme swaps values such as colors, typefaces, corner radius and illustration style behind shared token names. Component structure, behavior, accessibility, layout rules and the names themselves stay shared, so one fix reaches every brand.

open as a page

In a design system, how should a scoped sub-theme work when one region of a screen, such as an opposing faction's match panel, uses a different theme?

level: middleimportance: should knowfreq 40%

basics

~20 s

A sub-theme remaps the semantic values for one subtree, so components inside it change without knowing why. It must override a coherent set of values, carry its scope into overlays opened from inside, and pass contrast checks on its own surfaces.

open as a page

In a design system, how should components handle an operating-system setting that asks for more contrast versus one that replaces the app's colors entirely?

level: middleimportance: should knowfreq 38%

basics

~20 s

An increase-contrast setting is a request the app meets with a high-contrast value set. A color-replacement mode swaps the app's colors for the user's palette, so components must convey boundaries and state with borders, text and icons, not fills.

open as a page

In a design system's compact density mode, what goes wrong when a user raises the platform text size, and how should components cope?

level: middleimportance: should knowfreq 42%

basics

~20 s

Compact modes that fix row and control heights clip or overlap text when users enlarge it. Components should use minimum heights and padding, keep text in the platform's user-scalable unit, and grow, wrap or reflow as text grows.

open as a page

In a game companion app, a shared scoreboard component looks right in the app theme but breaks inside a faction-themed panel; what usually causes this, and how does a design system prevent it?

level: seniorimportance: should knowfreq 36%

basics

~20 s

The component assumed one theme: it hard-codes raw values, reads the app-level theme instead of its nearest scope, branches on a theme name or uses baked-color images. Prevent it with semantic-only references, nearest-scope resolution and tests rendering each component in every theme and scope.

open as a page

A multiplayer game's companion app shows the default theme for a moment before the player's saved faction theme appears; what causes this, and how do you fix it?

level: seniorimportance: should knowfreq 46%

basics

~20 s

The saved theme is resolved after the first render, usually from asynchronous storage or a profile request. Fix it by reading a locally stored theme identifier before first paint, applying it at the root, and reconciling with the account afterwards without a second visible switch.

open as a page

A telecom self-service app's compact density mode fails WCAG 2.2 criterion 2.5.8 because plan-table icon buttons are 18 by 18 CSS pixels and touching; how do you fix it without dropping compact?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Keep the small icons but give each a hit area of at least 24 by 24 CSS pixels, or space them so centres sit 24 pixels apart, per WCAG 2.2 criterion 2.5.8. Then fix it in the shared component, fix the minimum across modes and test compact too.

open as a page

In a food-delivery design system shared by two brands, one brand needs a component the other will not use. Where should it live, and what should you avoid?

level: seniorimportance: should knowfreq 32%

basics

~20 s

Put it in a brand extension layer built from core primitives and tokens and owned by that brand, promoting it to the core if a second brand needs it. Avoid brand checks inside core components and forked copies.

open as a page

A food-delivery company running two brands on one design system acquires a third brand. How do you estimate what adding it costs, and when would you decline?

level: principalimportance: should knowfreq 25%

basics

~20 s

Estimate the one-time cost (value set, design library, brand components, migration) and the cost repeated on every core release. Fit decides: a brand inside the override surface is cheap; one needing structural exceptions stays expensive.

open as a page