Execute code in component after the style has been applied to the template (new lifecycle hook ?)

Is there any way to do something in a component after all the style has been applied ?

For instance, I have a basic use case with an horizontal scrollbar with something like this :

  ngAfterViewInit(): void {
    const element = document.getElementById('someList');
    this.isScrollable = element.scrollWidth > element.clientWidth;
  }

However, it seems the styles from my css have not been applied yet, therefore scrollWidth and clientWidth have the same value.

I also tried with ngAfterViewChecked() but the result is the same. Maybe a new lifecycle hook could be added ?

How can I execute my code after the style has been applied ?

Also, here is the relevant CSS (I’m using scss if that matters) :

#someList {
    position: relative;
    top: 220px;
    display: flex;
    flex-direction: row;
    overflow-x: auto;
}

Currently, I have to use a timeout to make it work but obviously I’m not fond of this solution.

1 possible answer(s) on “Execute code in component after the style has been applied to the template (new lifecycle hook ?)

  1. It happens only once with Stackblitz because it caches the images.
    Your issue isn’t about css but the loading of the assets (here the images).

    When AfterViewInit is triggered, the images aren’t loaded yet into the browser.
    So not only the scrollWidth equals the clientWidth but both values equals the actual width of the browser (not the width required to display the images).

    Angular can’t catch the loading of the images on its own, you need to listen to the loading completion yourself.

    You can listen to the load event on images to do so :

    <!-- add a template reference to retrieve them -->
    <img #img src="{{element.img}}">
    @ViewChildren("img", { read: ElementRef }) imgs: QueryList<ElementRef>;
    
      elements = elements;
    
      ngAfterViewInit(): void {
        combineLatest([...this.imgs.map(img => fromEvent(img.nativeElement, 'load'))]).subscribe(() => {
           // once all images are loaded
          const element = document.getElementById("someList");
          console.log(element.scrollWidth);
          console.log(element.clientWidth);
          this.isScrollable = element.scrollWidth > element.clientWidth;
    
        if (this.isScrollable) {
          this.canScrollLeft = element.scrollLeft > 0;
          this.canScrollRight =
            element.scrollLeft < element.scrollWidth - element.clientWidth;
        }
        });
      }