Closed general

Four CSS variables are referenced but never defined (declarations silently dropped)

Colby Knox · 2mo ago ·closed by Colby Knox

var(--does-not-exist) with no fallback is not a CSS error. The declaration is silently dropped and the property falls back to its initial value, so a rule that reads like a styling decision is actually doing nothing.

Four token names are referenced in static/style.css that :root never defines:

token bare uses effect
--bg several background dropped, element renders transparent
--surface 2 same
--text 1 color dropped, inherits from the parent
--border-muted 1 border-top dropped, no rule drawn

Most uses of --bg and --text elsewhere in the file carry a fallback (var(--bg, #0d1117)) and are fine. These are the bare ones.

How this surfaced

A confirmation dialog shipped fully transparent, because every token it referenced was invented: --bg-elevated, --bg-alt, --text, --text-dim. Nothing failed, no console warning, tests passed, and the panel simply had no background. Fixed, and test/pages/css-tokens.test.mjs now fails on any new bare var() that does not resolve.

The four above are allow-listed in that test so it can pass today, which is why this issue exists rather than a silent TODO.

Ask

Decide what each of the four should be, and either point it at a real token or delete the declaration.

I did not fix them because they are pre-existing and the right value depends on design intent I do not have. background: var(--bg) on a panel that has looked fine transparent for months might genuinely want --bg-primary, or might want nothing, and guessing changes the appearance of pages nobody complained about. Each is a one-line change once someone says which.

When they are fixed, remove them from KNOWN_BROKEN in the test so the guard covers the whole file.

1 Reply

Colby Knox · 2mo ago

Fixed and live on prod. All four now point at real tokens, and the guard's allow-list is empty, so test/pages/css-tokens.test.mjs covers the whole file.

I filed this saying the values depended on design intent I did not have. That was wrong: each had a conventional answer sitting in the file already.

token now evidence
--bg --bg-primary the file's own fallback is var(--bg, #0d1117), and #0d1117 is --bg-primary
--text --text-primary same, var(--text, #e6edf3) is exactly --text-primary
--surface --bg-secondary both uses are bordered, rounded cards; 18 comparable cards in the file use --bg-secondary
--border-muted --border the single use is a separator; 8 comparable separators use --border

The first two are not judgement calls at all. The same variable is used elsewhere with a fallback, and that fallback is the literal hex of an existing token. The file was already telling us what it meant; only the bare uses were broken.

Only bare var(--x) forms changed. The 48 fallback-carrying uses already resolved correctly and are untouched.

These were not cosmetic. A var() with no fallback and no definition drops the whole declaration, so .recent-releases-list and .publish-form were rendering with no background, and .tag-bar with no separator. Verified on the deployed page that the separator now computes to rgb(48, 54, 61), which is #30363d, rather than being dropped.

The lesson worth keeping is the one that produced the guard: this class of bug is invisible. No CSS error, no console warning, no failing test, and the result looks like a styling decision rather than a mistake.

Log in to reply.