Using CSS Variables In Angular
Very common to an Angular programmer.”
The Dilemma
“As part of the requirements, I needed to be able to pass into this component the color for the ‘hover’, ‘active’ and ‘focus’ pseudo-classes for the button. This is where ngStyle stopped working and I had to come up with a different solution. It doesn’t work because you can’t set pseudo-classes (:hover, etc.) on the style property of an element (i.e. <button style=”:hover {background-color: blue}”> —- does not work“
Why doesn’t it work…? Because the pseudo-classes must be defined in CSS. Which is fine but how can you pass a variable to CSS using Angular? Let’s find out!
CSS Variables Primer
In short, the answer to my dilemma above was to use CSS variables (link). Let’s first learn the basics of CSS variables so we can understand how to use them in Angular.
A CSS variable takes this form:
:root {
--hoverColor: white;
}
- :root allows you to use this variable globally across the HTML document
- –hoverColor is the CSS variable
Then to use the CSS variable, use the “var” function:
button:hover {
background-color: var(--hoverColor, grey);
}
- If it isn’t defined, it will get the default “grey” value
How to Use the CSS Variable in Angular
So we learned about CSS variables but how do we take this knowledge and apply it to Angular? In other words, how can we pass a variable into the CSS so the CSS variable works? It turns out the answer depends on which version of Angular you are using.
For both solutions, these things remain the same:
- Define the “hoverColorVar” variable in the component Typescript:
export class AppComponent {
// Note it is important to set this to 'null' here to get the default color in css.
hoverColorVar: string = null;
}
- Use the –hoverColor CSS variable in the component CSS for ‘background-color’:
button:hover {
background-color: var(--hoverColor, grey);
}
- Regardless of how –hoverColor is bound to hoverColorVar, the CSS uses the bound value at the element (button in this case) scope.
For version 9 and after, it’s quite easy:
<button type="button" [style.--hoverColor]="hoverColorVar">Press Me</button>
- [style.–hoverColor] binds the hoverColorVar to the button style
- This solution is how you would expect it to work in Angular
After all, something like this is common: [style.color]=”textColorVar”
For version 8 and before, you just need to use the following directive (because [style.–hoverColor] was introduced in version 9 of Angular):
@Directive({ selector: "[bindCssVariable]" })
export class BindCssVariableDirective {
@Input("bindCssVariable") variable: string;
@Input("bindCssVariableValue") value: string;
constructor(private host: ElementRef<HTMLElement>) {}
ngOnChanges(changes) {
const value = changes.value.currentValue;
this.host.nativeElement.style.setProperty(`--${this.variable}`, value);
}
}
- Every time the bound value (bindCssVariableValue) changes, it calls setProperty on the style of the element, which binds bindCssVariableValue to the –hoverColor CSS variable
For the example above, you would use it like this:
<button type="button"
bindCssVariable="hoverColor"
[bindCssVariableValue]="hoverColorVar"
>
Press Me
</button>
Examples and Sources
Rich Franzmeier
Rich is a lead consultant, author, and another reason to consider Black Slate when you need help on your project!