Skip to content

Why I Put 92% Alpha in My Header Token Instead of Using bg-white/60

Adityo Guni Waluyo

Dark navy header felt heavy in light mode. The fix: bake 92% alpha into the --color-header token so backdrop-blur works everywhere without per-component overrides.

TL;DR

Slapping bg-white/60 on a navbar breaks fast, since child elements inherit transparency and fixes scatter across files. The fix is baking alpha into a --color-header token (about 92 percent opacity), which cascades to every consumer and pairs cleanly with backdrop-blur-md. Trade-off: the header decouples from the global background token, but one line brings it back if needed.

I opened my browser, refreshed the page, and immediately felt something was off. The dark navy header navigation suddenly felt heavy and out of place in light mode. The wordmark logo that looked sharp against the dark background was now either invisible or forcing the entire header to stay dark.

My first instinct? Slap bg-white/60 on the navbar component. Quick fix, problem solved. Except it was not. Every child element that needed a background or border started inheriting the transparency in weird ways. Buttons that should have been solid turned ghost. Changing one value meant hunting through multiple component files. Not sustainable.

The Token Approach with Alpha

The real fix was moving the transparency decision from the component level to the token level. I defined a CSS custom property --color-header with the value #F8FAFCEB. The last two characters, EB, encode roughly 92 percent opacity in hex. The F8FAFC part is a soft off-white base color. I then added backdrop-blur-md to the header element.

Why is this cleaner? First, backdrop-filter only works when the element or its background is transparent or semi-transparent [1]. With a solid color, there is nothing behind the element to blur. By baking the alpha into the token, every element consuming that variable automatically gets the right transparency without per-component overrides.

Second, CSS custom properties follow the cascade and inherit from their parent [2]. I can define different values for light and dark mode in the same file. Dark mode stays a solid opaque navy so the white wordmark stays readable. Light mode gets the soft glass effect. One declaration, all consuming elements update.

Third, backdrop-blur-md from Tailwind maps to roughly 12 pixels of blur [3]. Enough to create a visible frosted-glass effect without hammering the browser's compositor.

What I Did Not Touch

The navbar height, border, and shadow stayed exactly as they were. I did not use CSS shorthand that could reset related properties — a mistake I made on another project where background shorthand silently wiped out background-clip: text.

The hero section overlay also stayed untouched. I swapped its utility from bg-background/60 to bg-header/85 so it follows the same theme token. Light mode gets white glass, dark mode stays navy. One token change, every surface shifts — without touching individual components.

The Trade-off I Accepted on Purpose

This approach costs one thing: the light-mode navbar is now decoupled from the --background token. If the site's global background color ever changes, the header will not follow. I accepted that for two reasons. First, chrome elements like headers are usually meant to stay stable while content changes around them. Second, if per-theme navbar colors ever become a real need, the path is clear: add a --color-navbar token and swap bg-header for bg-navbar. One line.

Tokens for shared meaning, literals for component-specific personality, and knowing when to stop abstracting — that is the work.

Sources

Related articles