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>

2 Answers 2

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;
  `
);
Sign up to request clarification or add additional context in comments.

Comments

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.

3 Comments

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?
You can pass RendererStyleFlags2.DashCase as a 3rd argument to setStyle, no sanitizer needed
@dav1d This comment saved me, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.