Using The CSS Pseudo Element :host In Angular

Angular has a great CSS feature called “View Encapsulation”. It means that each component can have it’s own CSS that is encapsulated and applied to only that particular component/view. This does away with having to have great big long CSS declarations to try and narrow down the element you want to style. For example you probably have seen gnarly things like :

.main-page #header-wrapper #header-div #header-left-panel h1 span{

}

With Angular’s View Encapsulation that is no more (Well… Atleast most of the time).

But you may come across some situations where the view encapsulation gets in your way. Where you know the element you want to style, but the additions in the shadow dom are making things a headache. Luckily Angular adds in a couple of CSS Pseudo Elements that help you “break out” when you need to. These include :host, :host-context and ::ng-deep. Today we’ll do a dive on :host.

:host In A Nutshell

Imagine I create a component called “my-component” that’s pretty darn simple :

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template : `<p>This is my component</p>`,
  styleUrls: ['./my-component.component.scss']
})
export class MyComponentComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Now if I want to style the component itself? How do I do that? How can I style the <app-my-component>  tag? A beginners take might be to try some CSS/SASS like so :

app-my-component
{
    display:block;
    background-color:blue;
}

After all, I’m using the name of my tag inside itself so hopefully it should be recognized. Wrong. Angular view encapsulation means I can only style things “inside” the component, but not the component itself. Unless I use the :host pseudo element of course :

:host
{
    display:block;
    background-color:blue;
}

Remember this goes *inside* the components style file, and not in the root etc. Using :host I am able to self style the component! It’s almost like using the “this” keyword in Angular CSS syntax.

What Goes On Under The Hood?

When your view is compiled down, your components are given unique attributes to encapsulate styles from one other. So in my example, app-my-component actually gets output looking like :

<app-my-component _ngcontent-lsw-c0="" _nghost-lsw-c1="">
	<p _ngcontent-lsw-c1="">This is my component</p>
</app-my-component>

The way it works (in a simple way) is that each component is given an _nghost-unique-id . Each element that lives inside that component is then given an _ngcontent-unique-id  . Where the unique-id on the ngcontent label matches that of the parent nghost. Pretty smart stuff!

So that goes a ways to explain why when we try our beginners attempt of just using the component tag :

app-my-component
{
    display:block;
    background-color:blue;
}

It doesn’t work because the generated CSS actually looks like :

app-my-component[_ngcontent-lsw-c1] {
  display: block;
  background-color: blue;
}

So notice that it’s saying our tag should have an _ngcontent tag with a specific id but we are actually looking for the same tag with an _nghost.

When we check how it generates and outputs the :host tag, it looks like :

[_nghost-lsw-c1] 
{ 
	display: block; 
	background-color: blue; 
}

Makes sense! It outputs the exact tag it knows our component will have, allowing us to style the component itself, not just it’s children.

Leave a Reply

Your email address will not be published. Required fields are marked *