2026-10-16 · 6 min read · Rahul Chitturi
- css
- color
- theming
light-dark() picks one of two colors from the element's used color scheme. The first argument is the light color. The second is the dark color. If the used scheme is light or unknown, the computed value is the first color. Only a used scheme of dark selects the second.
The usual bug is a page that follows the operating system in every custom property and still paints the light argument. The function did not fail to read prefers-color-scheme. Nothing on the element opted into a dark scheme, so the used scheme stayed unknown and the first color won.
Set color-scheme on an element that actually inherits
The initial value of color-scheme is normal. normal does not tell the page that it supports a dark scheme, and light-dark() then resolves to the first argument. color-scheme: light dark on :root, or on the element that needs the switch, lets the user agent choose from the preference. color-scheme: dark forces the second argument even when the system is light. color-scheme: light forces the first.
The property inherits. A theme class that only swaps custom properties does not change it. If .dark sets --fg and leaves color-scheme alone, light-dark(var(--fg-light), var(--fg-dark)) stays on the light argument under that class. Put color-scheme: dark on the same element that owns the class, or stop using light-dark() for a class-driven theme.
- Confirm the declaration was not dropped as unsupported.
- Read the computed color-scheme, not the token file.
- Check :root and the element. A child can override the root.
- Separate a class toggle from the operating-system scheme.
Compare the painted hex, not the function text
The specified value can still show light-dark(...). The computed value is one color. Copy that computed sRGB hex from the element that looks wrong, in the theme you are testing. A browser that does not implement the function drops the whole declaration, and an older rule then paints. That also looks like a stuck light color.
Flashman's color tool converts a 6-digit hex and reports WCAG contrast with the 0.03928 linearization cutoff. It does not evaluate light-dark() or color-scheme. The CSS formatter only pretty-prints the rule. Paste the computed hex pair, and diff the stylesheet against the computed value when the source and the paint disagree.