Angular: Use Renderer 2 to Add CSS Variable
Asked Answered
N

2

3

Is it possible to add inline style css variable using Renderer2?

I tried the following but it doesn't work.

import { Component, OnChanges, Output, ViewChild, Renderer2, ElementRef, ViewEncapsulation } from '@angular/core';

@Component({
})
export class CollapsibleComponent implements OnChanges {

  @ViewChild('collapsibleContent') collapsibleContent: ElementRef;

  constructor(
    private renderer: Renderer2
  ) { }

  ngOnChanges() {
    this.measureCollapsibleContents()
  }

  measureCollapsibleContents() {
    this.renderer.setStyle(this.collapsibleContent.nativeElement, '--expanded', this.collapsibleContent.nativeElement.firstElementChild.offsetHeight + 'px' )
  }

}

'--expanded' isn't a proper css property so angular won't add any style to my div.

If I do add a proper css property it will work like the code below.

this.renderer.setStyle(this.collapsibleContent.nativeElement, 'top', this.collapsibleContent.nativeElement.firstElementChild.offsetHeight + 'px' )

the output for my div will be

<div style="top: 160px">...</div>

I would like to achieve something like below

<div style="--expanded: 160px">...</div>

I have also tried [ngStyle] but that also doesn't render any value but the style attribute.

[ngStyle]="{'--expanded': expandedHeight }"

Outputs to

<div style>...</div>
Noisemaker answered 21/2, 2018 at 22:33 Comment(0)
M
3

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.

Monocoque answered 11/6, 2018 at 14:2 Comment(3)
I would like to set the css variable using Renderer2, before using the same renderer to add a class triggering a transition. How would you use bypassSecurityTrustStyle with renderer.setStyle?Oilskin
You can pass RendererStyleFlags2.DashCase as a 3rd argument to setStyle, no sanitizer neededEnclosure
@Enclosure This comment saved me, thank you!Recruitment
I
4

For those using the latest Angular versions. You can implement it either of these:

Use Renderer's setProperty instead of setStyle

Example #1: Setting 1 CSS variable

this.renderer.setProperty(
  // it can be this.elementRef.nativeElement 
  // or this.document.documentElement or any similar
  <ELEMENT>, 

  // we will set the "style" property of the element
  'style',   

  // the CSS variable you want to declare
  // be sure to encapsulate it in a back tick (`)
  `--height: ${this.height}px`     
);

Example #2: Setting multiple CSS variables all at once

NOTE: If you're dealing with multiple CSS variables, avoid implementing it separately as what was done in Example #1 above, as this will replace those initially declared CSS variables and will only end up with registering the last setProperty code

this.renderer.setProperty(
  // it can be this.elementRef.nativeElement 
  // or this.document.documentElement or any similar
  <ELEMENT>, 

  // we will set the "style" property of the element
  'style',

  // the CSS variables you want to declare 
  // be sure to encapsulate all of them in a back tick (`)
  `
      --height: ${this.height}px;
      --width: ${this.width}px;
  `
);
Isochronism answered 30/9, 2022 at 15:40 Comment(0)
M
3

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.

Monocoque answered 11/6, 2018 at 14:2 Comment(3)
I would like to set the css variable using Renderer2, before using the same renderer to add a class triggering a transition. How would you use bypassSecurityTrustStyle with renderer.setStyle?Oilskin
You can pass RendererStyleFlags2.DashCase as a 3rd argument to setStyle, no sanitizer neededEnclosure
@Enclosure This comment saved me, thank you!Recruitment

© 2022 - 2024 — McMap. All rights reserved.