Angular Material Custom Theme Not Applying: A Diagnostic Guide
Your Angular Material custom theme compiles without errors but components still show default colors. A diagnostic walkthrough of the five most common causes, ordered checks, and fixes.
07 Aug 2026, 01:11 UTC

The recognizable condition
You defined a custom theme in SCSS — custom primary and accent palettes, maybe a dark variant — but your buttons, toolbars, and form fields still render in the default indigo-pink colors. The build succeeds with no errors, which is exactly what makes this frustrating: Angular Material theming fails silently in most of these cases. This guide walks through the checks in the order most likely to find the cause, from most common to least.
Assumptions: this applies to Angular Material's Sass-based theming API (the mat.define-light-theme / legacy mat-light-theme mixins) used with Angular CLI. Version specifics are noted where the API changed.
Cause and diagnostic summary
| Symptom | Likely cause | First check |
|---|---|---|
| No custom colors anywhere; default theme everywhere | Theme file never imported, or theme mixins never included | Inspect compiled CSS in dev tools for your primary hex value |
| Some components themed, others default | Only mat.core() included, or per-component theme mixins missing | Check which mat.*-theme(...) mixins are called |
Build error referencing mat-core or mat-light-theme | Version mismatch between mixin names and installed Material version | Compare @angular/material version in package.json against mixin syntax |
| Theme works globally but one component ignores it | Component-scoped styles or encapsulation overriding theme CSS | Inspect that component's computed styles for local overrides |
| Theme applies, then disappears after a lazy-loaded route | Theme styles bundled in a lazily loaded stylesheet instead of global styles | Check where the theme import lives in the module/style tree |
Check 1: Confirm the theme is actually compiled
Open the app in a browser, open dev tools, and inspect a mat-raised-button with color="primary". Look at its computed background-color. If it is the default indigo (#3f51b5 in older versions), your theme CSS never made it into the bundle.
The most common reason: the theme file exists but nothing imports it. Your global styles.scss (the one listed under projects.<name>.architect.build.options.styles in angular.json) must contain the import and the mixin invocations. A minimal working setup for Angular Material 15+ looks like this:
@use '@angular/material' as mat;
@include mat.core();
$my-primary: mat.define-palette(mat.$teal-palette);
$my-accent: mat.define-palette(mat.$amber-palette, A200, A100, A400);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
)
));
@include mat.all-component-themes($my-theme);Two failure modes hide here. First, defining the theme map but never calling @include mat.all-component-themes($my-theme) — the Sass compiles fine but emits no component CSS. Second, importing the theme file into a component stylesheet instead of the global one; depending on your setup, that either scopes it away or duplicates it per component.
Fix: ensure the import and the @include calls live in the global stylesheet referenced by angular.json, then restart ng serve (style entry-point changes are not always picked up by hot reload).
Check 2: Rule out version-mismatched mixin syntax
The theming API changed substantially across major versions. Material 15 (M3-based components) introduced mat.define-light-theme with a color map; older versions used mat-light-theme($primary, $accent, $warn) and mat-core() (with a hyphen). If your project was upgraded but the theme file was copied from an old tutorial — or vice versa — you can get silent partial output or build errors.
Run, in the project root (no special permissions needed):
npm ls @angular/material @angular/coreExpect both to report the same major version. Then confirm your mixin names match that major version's documented theming API. If npm ls shows two different versions of @angular/material (a duplicate in the tree), resolve that first — duplicated packages can produce components styled by one copy while your theme targets the other.
Check 3: Check for overrides and encapsulation traps
If the theme is compiled but a specific component still shows wrong colors, inspect that element in dev tools and look at which rule wins. Common culprits:
- A component stylesheet setting
background-colordirectly on.mat-mdc-raised-buttonor similar internal classes, with higher specificity than the theme rule. !importantin local styles suppressing theme colors. Beyond breaking the theme, this makes future Material upgrades painful — remove the override rather than fighting it with more!important.ViewEncapsulation.ShadowDomon a component, which blocks global stylesheets from reaching its template. Theme classes applied inside that shadow root will not match global rules.
Fix: prefer the documented theming surface over piercing encapsulation. For one-off overrides, define a second theme class or use Material's density/typography/color mixins scoped to a selector rather than targeting internal DOM. If you must style inside a shadow root, move that styling into the component's own stylesheet — do not reach for ::ng-deep as a first resort; it is deprecated and leaks unpredictably.
Check 4: Verify the result objectively
After each fix, verify rather than assume:
- Re-run
ng serveorng buildand reload with cache disabled. - Inspect the test button's computed
background-colorand compare it to the500hue of your primary palette (e.g., teal's#009688). - For a build-level check, run
ng buildand search the emittedstyles.*.cssindist/for your primary hex value. If it is absent, the theme still is not being compiled — go back to Check 1.
When to escalate
Escalate beyond local debugging when: npm ls shows unresolvable duplicate Material versions (a dependency-graph problem, not a theming problem); the theme works in ng serve but not in the production build (points at build configuration, e.g., style preprocessor options or CSS extraction order — compare the two angular.json configurations); or you are migrating between major versions and the palette API itself changed, which warrants following the official upgrade guide rather than patching mixins one at a time. In all cases, capture the Material version, the exact theme file, and the computed-style evidence before handing off — it turns a vague "theme broken" report into an actionable one.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.