How can I add separate CSS for one page in Angular?
I've discounted both of the standard solutions to this problem:
Using ::ng-deep
or ViewEncapsulation.None
. CSS added in this way won't be removed when navigating away from the component, so this won't work for us.
Adding a class to the <body>
via ngOnInit/ngOnDestroy
. The CSS I want to add can't be attached to the <body>
, so this isn't good either.
Example CSS:
@media print{
@page{
margin:0;
}
body{
margin:30px;
}
}
I've created a Stackblitz which explains the problem clearly.
Maybe the question would be better summarized as "How to add global CSS, but remove it when we leave the page?".
Solved!
We print the <style>
block directly into the component's HTML, and therefore when the component gets removed, our <style>
block gets removed too.
First, create a new component to handle the work:
component.ts: (Only this. You don't need an HTML or style.css file)
// Usage Instructions:
// Inside your local component, place this HTML
// <app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
// <app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
@Component({
selector: "app-local-css",
template: '<span style="display:none" [innerHTML]="this.safeString"></span>'
})
export class LocalCSSComponent implements OnInit {
constructor(protected sanitizer: DomSanitizer) {}
@Input() scriptURL?: string;
@Input() style?: string;
safeString: SafeHtml;
ngOnInit() {
if (this.scriptURL) {
let string = '<link rel="stylesheet" type="text/css" href="' + this.scriptURL + '">';
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
} else if (this.style) {
let string = '<style type="text/css">' + this.style + "</style>";
this.safeString = this.sanitizer.bypassSecurityTrustHtml(string);
}
}
}
And then use it like this:
mySample.component.html:
<app-local-css [style]="'body{background:green !important;}'"></app-local-css>
// OR
<app-local-css [scriptURL]="'/path/to/file.css'"></app-local-css>
Here's a StackBlitz.
(Note that without this component, printing a <style>
block directly into the HTML wouldn't work because Angular would sanitize it away, moving it into the <head>
, which would prevent it from getting deleted when the component is gone. Here it works correctly because of DomSanitizer.bypassSecurityTrustHtml
.)