My Light-Mode Navbar Uses bg-white/60, Not the Token
Brightening the shared background token shifts the whole page. A navbar needs a solid chrome feel, so a literal color plus the dark variant wins.
TL;DR
Light mode made the navbar look like dirty glass because the shared background token added a grayish cast. The fix swaps in literal bg-white utilities for light mode in both scroll branches while dark mode keeps the token. Trade-off: the navbar won't follow future theme changes, but a dedicated token is a one-line swap later.
My translucent navbar looked watery in light mode. The backdrop blur worked, the bottom border was neat, but the background carried a grayish cast from the background token, so on bright pages the navbar read as dirty glass instead of a surface that stands. This commit fixes it with a design decision I initially resisted: a literal color instead of the theme token.
My Wrong Guess: Just Brighten the --background Token
My first instinct was to change the token value. Tailwind's color store is designed as design tokens: theme variables in the --color-* namespace produce utilities like bg- and text- across the project [1]. If the navbar is too dark, brighten --background and you are done. One change, every surface follows.
That is exactly the problem. The background token in my app is shared by cards, panels, and sections. Brightening it for the navbar's sake shifts the whole page, and then I would be fighting the fallout in the one place that should not change. The navbar plays a different role from content: it is chrome, the control surface that must read as solid above whatever scrolls beneath it. That "solid white" feel is not a property of my theme; it is a property of the navbar.
Literal Color in Light, Token Stays in Dark
The change in Navbar.tsx touches only the two scroll branches:
scrolled
? "border-b border-border/60 bg-white/90 shadow-[0_8px_32px_rgba(0,0,0,0.08)] backdrop-blur-2xl dark:bg-background/70"
: "border-b border-transparent bg-white/60 backdrop-blur-xl dark:bg-background/40"
Before, both branches used bg-background/90 and bg-background/40 for both modes. Now light mode gets bg-white/90 when scrolled and bg-white/60 at the top, while dark mode stays on the token through the dark: variant. This follows the official documentation pattern: light utility written directly, dark: overriding it for dark mode [2]. Behind that variant, the preference comes from prefers-color-scheme, the media feature that reports the user's system theme choice [3].
What I did not touch matters just as much. Navbar height, blur, border, and shadow stay; I did not repeat my old mistake of swapping one property through a shorthand that resets its siblings. The 60 and 90 percent values give two levels of opacity: transparent enough at the top of the page that content still registers, nearly solid once the user has scrolled away from the top.
The Trade-off I Knowingly Accept
This decision costs one thing: the navbar no longer follows the theme if --background ever changes wholesale. I accept that for three reasons. First, chrome is conventionally stable; it should contrast with content that changes. Second, if theming the navbar ever becomes a real need, the path is clear: create a dedicated token like --color-navbar and swap bg-white for bg-navbar, a one-line change. Third, a crisp light-mode signal is worth more today than hypothetical flexibility. Tokens for values that share meaning, literals for the feel of one component, and knowing when to stop abstracting is part of the job.