Control CSS variable from Angular 5
Yes you can set variables in root scope:
:root {
--main-color: red
}
Yes you can use :host
selector to target element in which the component is hosted.
:host {
display: block;
border: 1px solid black;
}
You can also use, :host-context
to target any ancestor of the component. The :host-context() selector looks for a CSS class in any ancestor of the component host element, up to the document root.
:host-context(.theme-light) h2 {
background-color: #eef;
}
Note: ::ng-deep
or /deep/
or >>>
has been deprecated.
Read more about it here: special css selectors in angular
Just an additional information.
It works both inside ':root' as well as ':host'
We can set values to them by:
constructor(private elementRef: ElementRef) { }
thenthis.elementRef.nativeElement.style.setProperty('--color', 'red');
Change css variables dynamically in angular
You can update them using
document.documentElement.style.setProperty('--theme-color-1', '#fff');
If u want to update many values, then create a object
this.styles = [
{ name: 'primary-dark-5', value: "#111" },
{ name: 'primary-dark-7_5', value: "#fff" },
];
this.styles.forEach(data => {
document.documentElement.style.setProperty(`--${data.name}`, data.value);
});
The main thing here is document.documentElement.style.setProperty
. This line allows you to access the root element (HTML tag) and assigns/overrides the style values.
Note that the names of the variables should match at both places(css and js files)
if you don't want to use document API, then you can use inline styles on HTML tag directly
const styleObject = {};
this.styles.forEach(data => {
styleObject[`--${data.name}`] = data.value;
});
Then In your template file using ngStyle (https://angular.io/api/common/NgStyle)
Set a collection of style values using an expression that returns
key-value pairs.<some-element [ngStyle]="objExp">...</some-element>
<html [ngStyle]="styleObject" >...</html> //not sure about quotes syntax
Above methods do the same thing, "Update root element values" but in a different way.
When you used :root
, the styles automatically got attached to HTML tag
Generate dynamic css based on variables angular
Direct approach available in angular is using ngstyle as follows
<div [ngStyle]="{'color': style.colorVal ? style.colorVal : '#000', 'font-size' : style.fontSize ? style.fontSize : '16px' }"></div>
After going through different methods and approached to add dynamic css to all pages on angular app I ended up with following solutions.
Requirement : generate dynamic css based on values returned from and API to change design and styling.
Solution :
- create a new component and create a service to load dynamic css variables from API.
- Add style tag in template file and use variable values for properties.
- Load this template on all pages or on main template.
- On app build style will be moved to head tag.
Code sample
import { CssService} from './Css.service';
@Component({
selector: 'DynamicCss',
templateUrl: './DynamicCss.component.html',
styleUrls: ['./DynamicCss.component.scss']
})
export class ServiceProviderComponent implements OnInit {
cssVariables: any;
constructor(private cssService:CssService){
/* call the service/api to get the css variable values in cssVariables */
}
}
Now apply css using jquery or javascript to append css with help of function like following
appendCss(customData)
{
let text = '.custom-form-1 {
background-image: url("`+customData.background_image+`");
}';
$(document).ready(function(){
$("style").append(text);
});
}
and call this function after loading custom data from service or other variable like I did it ngOnInit
ngOnInit(){
this.appendCss(this.customizeFormData);
}
Its using jquery but can be done with javascript/typescript as well if you dont want to use jquery in your angular app
Other useful resource https://github.com/angular/angular/issues/9343#issuecomment-312035896
Change the values of CSS variables at runtime in Typescript
Since these values are defined at root level, you can just update them using document. I am not exactly sure on how you can access the document in angular, but once you have document, you can do something like this:
document.documentElement.style.setProperty(`--${your-variable}`, value + suffix); //suffix may be px or ''
This way, you will directly set the css variable which will take effect at all the places and you will not have to target individual elements.
Angular 5: How to define color pallet in a central file
A nice and modern way, would be to use css variables. Global support is pretty good, and it has been recommended by the angular community.
import { Component, Renderer2 } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1> Hello </h1>
<h2> World </h2>
`,
styles: [
'h1 { color: var(--primary); }',
'h2 { color: var(--accent); }'
]
})
export class AppComponent {
constructor() { }
ngOnInit() {
const colors = new Map([
['primary', 'blue'],
['accent', 'red'],
])
Array.from(colors.entries()).forEach(([name, value]) => {
document.body.style.setProperty(`--${name}`, value);
})
}
}
Live demo
Angular: Use Renderer 2 to Add CSS Variable
Angular sanitizes CSS variables set in property bindings. You can bypass this behavior with DomSanitizer.
@Component({
selector: 'my-app',
template: `
<button (click)="dec()">-</button>
<button (click)="inc()">+</button>
<div [style]="style"> My height is set by CSS Variable </div>
`,
styles: [`
div {
height: var(--height);
}
`
]
})
export class AppComponent {
height = 50;
get style() {
return this.sanitizer.bypassSecurityTrustStyle(`--height: ${this.height}px`);
}
constructor(private sanitizer: DomSanitizer) { }
inc() {
this.height += 10;
}
dec() {
this.height -= 10;
if (this.height <= 0) {
this.height = 0;
}
}
}
Live demo
You might find this article interesting. It goes into details on theming Angular components with CSS variables.
Related Topics
Difference Between Float and Align Property in CSS
How to Place Div Inside Another Div to Absolute Position
Div with Scrollbar Inside Div with Position:Fixed
Ckeditor - Prevent Adding Image Dimensions as a CSS Style
Best Way to Use Media Queries for Mobile Designs
How to Make a Fluid Sticky Footer
How to Prevent Child's Content from Stretching Parent's Width
Svg Transform="Rotate(180)" Does Not Work in Safari 11
How to Capitalize the First Letter of Each Word in CSS
How to Make a CSS Triangle with Smooth Edges
How to Make One Circle Inside of Another Using CSS
What Is the Default Style of the Blue Focus Outline in Chrome
What Is the Function of "Overlay" Value of "Overflow" Property
CSS Link Element Jumps on Hover
How to Filter and Show Only Applied CSS in Chrome Developer Tools (Like Firebug in Firefox)