nuxt / nuxt/ui

[v4] Custom `--ui-*` CSS variable overrides in `@layer base` are silently reverted by `@layer theme` after view transitions / color-mode re-application

Open
#6,172 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
TypeScript
Stars
6.9k
Forks
1.1k
Avg merge
1d 7h
Merged PRs (30d)
57

Description

Environment
  • Operating System: macOS
  • Nuxt Version: 4.3.1
  • Nuxt UI Version: 4.5.1
  • Color Mode: @nuxtjs/color-mode with preference: "dark"
  • Experimental: viewTransition: true
Reproduction
  1. In main.css, override --ui-bg with a semi-transparent value inside @layer base:
@layer base {
  .dark {
    --ui-bg: rgba(11, 16, 33, 0.82);
  }
}
  1. Enable view transitions in nuxt.config.ts:
experimental: {
  viewTransition: true,
}
  1. Load the page, the transparent background works correctly.
  2. Navigate to another page and back, OR trigger a component re-render that causes @nuxtjs/color-mode to re-apply the .dark class.
Description

Custom --ui-* CSS variable overrides placed in @layer base (as one would naturally do following Tailwind/CSS conventions) are silently overridden by Nuxt UI's own .dark declarations in @layer theme.

This creates a particularly confusing bug:

  • On initial load, the custom values appear to work correctly (e.g., --ui-bg: rgba(11, 16, 33, 0.82) renders translucent card backgrounds).
  • After a view transition (page navigation) or any event that causes @nuxtjs/color-mode to re-apply the .dark class, the values revert to Nuxt UI's opaque defaults from @layer theme (e.g., --ui-bg becomes oklch(20.8% 0.042 265.755)).

This happens because CSS @layer theme always takes precedence over @layer base in the cascade, regardless of selector specificity. Since Nuxt UI defines its .dark { --ui-bg: var(--ui-color-neutral-900); } in @layer theme, any user customization in @layer base will lose.

Workaround: Move custom --ui-* overrides outside of any @layer (unlayered CSS always wins over layered CSS):

/* Outside any @layer — wins over @layer theme */
.dark {
  --ui-bg: rgba(11, 16, 33, 0.82);
}

This is non-obvious (and undocumented?)

Expected behavior

Custom --ui-* variable overrides in @layer base should reliably persist across view transitions, color-mode re-applications, and component re-renders — or the documentation should clearly state which layer/approach to use for overrides.

Suggested fixes
  1. Documentation: Clearly document that --ui-* theme variables live in @layer theme, so user overrides in @layer base will not persist. Recommend unlayered CSS or a specific override pattern.
  2. API improvement: Provide a supported mechanism (e.g., via app.config.ts or a composable) to override --ui-bg and similar semantic variables without CSS layer conflicts.
Related issues
  • #3075 — Same root cause (@layer ordering prevents --ui-* overrides), manifested with ssr: false
  • #3914 — Feature request for a runtime API to override CSS variables
  • #4218 — Can't override --ui-border default color (same family of issues)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the main.css reproduction and nuxt.config.ts settings for viewTransition and color mode, then review the related issues #3075, #3914, and #4218. Confirm that the override changes after navigation or color-mode re-application, and establish whether the accepted fix is documentation of the supported CSS pattern or an API improvement that keeps overrides persistent.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, nuxt, tailwindcss, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.