I am using Angular Material v19 (MDC) along with custom Angular components (e.g., headerponent.ts) in my project. Inside these components, I often use Material components like mat-button, but with custom classes (e.g., .manage-button).
I need to apply different styles (e.g., background color, text color) to my custom components and buttons depending on the current route. For example:
- On /dashboard, the background color of the headerponent should be blue, and the .manage-button inside it should be light-blue.
- On /company, the same headerponent should have a green background, and .manage-button should be white.
My Requirements:
- Styles should change based on routing.
- All route-specific colors should be defined in a single SCSS file for easy maintenance.
- Some styles affect custom components like headerponent, and some styles apply to Material components like mat-button with custom classes (e.g., .manage-button).
My questions:
- What is the best practice to handle route-based styling for custom components + Material components?
- How should I combine Material theming APIs like mat.button-theme() with my own custom component styles in such a setup?
I am using Angular Material v19 (MDC) along with custom Angular components (e.g., headerponent.ts) in my project. Inside these components, I often use Material components like mat-button, but with custom classes (e.g., .manage-button).
I need to apply different styles (e.g., background color, text color) to my custom components and buttons depending on the current route. For example:
- On /dashboard, the background color of the headerponent should be blue, and the .manage-button inside it should be light-blue.
- On /company, the same headerponent should have a green background, and .manage-button should be white.
My Requirements:
- Styles should change based on routing.
- All route-specific colors should be defined in a single SCSS file for easy maintenance.
- Some styles affect custom components like headerponent, and some styles apply to Material components like mat-button with custom classes (e.g., .manage-button).
My questions:
- What is the best practice to handle route-based styling for custom components + Material components?
- How should I combine Material theming APIs like mat.button-theme() with my own custom component styles in such a setup?
2 Answers
Reset to default 1In the component that contains the <router-outlet />
@Component({
imports: [RouterOutlet],
template: `
<router-outlet />
`,
host: {
'[class]': 'clazz()',
},
})
export class App {
#router = inject(Router);
currentRoute = toSignal(
this.#router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.router.url)
),
{ initialValue: '' }
);
// probably missing some nuance
// or use `endsWith()` or `includes()`
clazz = computed(() => {
const route = this.currentRoute();
if (route.startsWith('/company')) {
return 'company';
} else if (route.startsWith('/dashboard')) {
return 'dashboard';
} else {
return '';
}
});
}
That will apply the respective class to the whole component tree with those routes.
And then as far as Material styling goes in the desired SCSS file (the component with the router, or a "root" style file declared in the architect > build > options> styles
array of the angular.json
), use the "Styling" tab of a given component to find respective overrides.
@use '@angular/material' as mat;
pany {
@include mat.button-overrides(
(
filled-container-color: blue,
filled-label-text-color: white,
)
);
}
.dashboard {
@include mat.button-overrides(
(
filled-container-color: white,
filled-label-text-color: black,
)
);
}
As for stuff like the header component, you could scope the header's selector inside of one of those classes above, or in the header component check the current route and apply styles conditionally in the component.
First head to the styling
tag of angular material components:
Material Button Styling
Get the customizations ready and use the below code, to add the styling based on the component, below is a sample of how it will look:
Global styles method:
If you are not a fan of ::ng-deep
(Since it's usage is frowned upon by the community) you can add a class to the root route, this will be used to style the children
HOME:
<div class="class-to-customize-children">
<!-- child HTML and components rendered directly or through routing -->
</div>
Then in the global styles add the following:
@use '@angular/material' as mat;
.class-to-customize-children {
@include mat.button-overrides((
filled-container-color: orange,
filled-label-text-color: red,
));
}
ng-deep method:
@use '@angular/material' as mat;
:host ::ng-deep {
@include mat.button-overrides((
filled-container-color: orange,
filled-label-text-color: red,
));
}
We use :host
-> so that it applies styling only to the current component and it's children.
We use ::ng-deep
-> so that it applies styling to angular material elements, which bypasses view encapsulation.
This is a component based approach, if you want a routing based approach.
When you visit and route and it sub routes, add the styling using the above method to the root component of the route, where the customizations will vary.
For example styling home/contact
sub component add the styling to the route route homeponent.scss
, these customizations will get applied to both home and home's children (contact component
).