Skip to content

CSS Variable Namespacing - #68846

Closed
mattrbeck wants to merge 5 commits into
angular:mainfrom
mattrbeck:css_var_namespacing
Closed

CSS Variable Namespacing#68846
mattrbeck wants to merge 5 commits into
angular:mainfrom
mattrbeck:css_var_namespacing

Conversation

@mattrbeck

@mattrbeck mattrbeck commented May 20, 2026

Copy link
Copy Markdown
Member

Superseds #67362. Primary differences are:

  • Opt-out syntax is now a --global prefix, e.g. --global--foo: blue
  • Added support for style properties, e.g. [style.--foo]="'blue'"
  • Added errors for prefix missing trailing double-hyphen, e.g. --global-foo

This adds CSS variable namespacing support to Angular.

This allows multiple apps to coexist on the same page with isolated CSS variables, meaning one can use color: var(--primary-color); without worrying about accidentally inheriting the primary color of a different app which happens to set it on an ancestor element.

To enable this feature, call provideCssVarNamespacing in your app.config.ts. Typically you want to configure this with the same value as APP_ID, but with an additional separator at the end (a - or _):

import {ApplicationConfig, APP_ID} from '@angular/core';
import {provideCssVarNamespacing} from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: APP_ID,
      useValue: 'my-app',
    },
    provideCssVarNamespacing('my-app_'),
  ],
};

This only namespaces styles in Angular components (the styles or styleUrls properties in @Component). It does not namespace global styles, which are out of scope for this effort.

Namespacing does naturally break any JavaScript references to CSS variables, therefore this PR also introduces CssVarNamespacer which allows you to automatically namespace variables based on what is configured in the application.

import {CssVarNamespacer} from '@angular/platform-browser';

const namespacer = inject(CssVarNamespacer);
const color = namespacer.namespace('--primary-color');
getComputedStyle(someElement).getPropertyValue(color);

Libraries should consider always using the namespacer when referring to CSS variables, as they may be consumed by applications which enable namespacing.

Namespacing works by having the compiler unconditionally prepend %NS% to CSS variables (--foo -> --%NS%foo) and then at runtime replaces %NS% with a namespace specified by provideCssVarNamespacing('my-app_') (--%NS%foo -> --my-app_foo).

Internal bug: b/485672083


Closes #67362 via supersession.

@pullapprove
pullapprove Bot requested review from crisbeto and kirjs May 20, 2026 23:47
@angular-robot angular-robot Bot added the detected: feature PR contains a feature commit label May 20, 2026
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch from 6c27311 to 302644d Compare May 21, 2026 00:01
@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label May 21, 2026
@ngbot ngbot Bot added this to the Backlog milestone May 21, 2026
@mattrbeck
mattrbeck requested review from dgp1130 and removed request for kirjs May 21, 2026 00:02
@pullapprove
pullapprove Bot requested a review from atscott May 21, 2026 00:03
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch from 302644d to e95f942 Compare May 21, 2026 00:22
Comment thread packages/platform-browser/src/dom/dom_renderer.ts Outdated
Comment thread packages/platform-browser/src/dom/dom_renderer.ts
// Validate that the whole `--foo` variable is passed in.
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (!name.startsWith('--')) {
throw new Error(

@SkyZeroZx SkyZeroZx May 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a RuntimeError ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that RuntimeError is more for errors from framework internals that might not present clean stack traces and warrant additional documentation. The precedent I see is using Error in cases like this.

Comment thread packages/platform-browser/src/dom/css_var_namespacer.ts Outdated
Comment thread packages/platform-browser/src/dom/dom_renderer.ts Outdated
Comment thread packages/platform-browser/src/dom/css_var_namespacer.ts Outdated
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch from e95f942 to 5dd7961 Compare May 22, 2026 00:24
@mattrbeck mattrbeck added area: core Issues related to the framework runtime target: minor This PR is targeted for the next minor release labels May 22, 2026

@dgp1130 dgp1130 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, no major concerns on my end. Thanks for taking this on @mattrbeck!

Comment thread packages/compiler/src/shadow_css.ts
Comment thread packages/compiler/src/shadow_css.ts Outdated
Comment thread packages/compiler/test/shadow_css/shadow_css_spec.ts
Comment thread packages/platform-browser/src/dom/dom_renderer.ts Outdated
Comment thread packages/platform-browser/src/dom/dom_renderer.ts
Comment thread packages/compiler/src/shadow_css.ts Outdated
Comment thread packages/compiler/src/template_parser/binding_parser.ts Outdated
Comment thread packages/platform-browser/src/dom/dom_renderer.ts Outdated
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch 2 times, most recently from 3c2ce20 to af7d747 Compare June 10, 2026 00:02
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch from af7d747 to 73bad82 Compare June 30, 2026 15:38
mattrbeck added 4 commits July 1, 2026 06:41
Adds logic to inject symbols into CSS variables for runtime namespacing.
The runtime now replaces instances of `%NS%` with a namespacing
variable, limiting reach of CSS variables to the current app. An opt-out
syntax of a `--global` prefix allows users to avoid this behavior.
Using `--global-foo` is now prohibited. We suspect these cases will
likely be typos of `--global--foo` in the future, so we blanket ban them
and direct users to the expected syntax.
Adds support for namespacing css variables in style properties. Behaves
as you'd expect following the implementation for stylesheets generally.

This change also moves the error message into a util function since we
now need to produce the same error in three places.
... for now. Should be enabled in the next major.
@mattrbeck
mattrbeck force-pushed the css_var_namespacing branch from 73bad82 to 9c1a257 Compare July 1, 2026 13:41
@mattrbeck mattrbeck added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note and removed target: minor This PR is targeted for the next minor release labels Jul 2, 2026
@mattrbeck

Copy link
Copy Markdown
Member Author

Caretaker: TGP is green as of July 1. Possibility for backslide if a new CSS variable beginning with --global- is added in g3, but the solution is simply to rename the variable if this happens. My approach has just been to change "global" to a suffix.

@mattrbeck mattrbeck added target: minor This PR is targeted for the next minor release and removed target: patch This PR is targeted for the next patch release labels Jul 6, 2026
@leonsenft

Copy link
Copy Markdown
Contributor

This PR was merged into the repository. The changes were merged into the following branches:

@leonsenft leonsenft closed this in f985476 Jul 6, 2026
leonsenft pushed a commit that referenced this pull request Jul 6, 2026
Using `--global-foo` is now prohibited. We suspect these cases will
likely be typos of `--global--foo` in the future, so we blanket ban them
and direct users to the expected syntax.

PR Close #68846
leonsenft pushed a commit that referenced this pull request Jul 6, 2026
Adds support for namespacing css variables in style properties. Behaves
as you'd expect following the implementation for stylesheets generally.

This change also moves the error message into a util function since we
now need to produce the same error in three places.

PR Close #68846
leonsenft pushed a commit that referenced this pull request Jul 6, 2026
... for now. Should be enabled in the next major.

PR Close #68846
@angular-automatic-lock-bot

Copy link
Copy Markdown

This pull request has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Aug 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker area: compiler Issues related to `ngc`, Angular's template compiler area: core Issues related to the framework runtime compiler: styles core: CSS encapsulation core: stylesheets detected: feature PR contains a feature commit merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants