Angular Component styling — Using shadow piercing descendant selector

Madhu Sudhanan
3 min readJan 24, 2018

--

In this post, I am going to share how the shadow piercing descendant selector helped me with style scoping problem.

Well, I tried to create Angular wrapper for one of a JQuery plugin. All worked as planned and later I noticed that I was not able to apply custom styles to the plugin in ViewEncapsulation.Emulated mode. I can set the custom style when the ViewEncapsulation is set to None.

So I started to search for a solution to apply the custom style in ViewEncapsulation.Emulated mode.

@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
styles: [`h2 {
color: red
}`]
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`

}
}

Extra attribute will be added to the template elements as follows.

Component style with extra attribute
Component template with extra attribute

Why component style is not applied to the JQuery plugin?

Inside the plugin the element creation is done by JQuery instead of Angular. So the attributes used to emulate style scoping is not added to the elements.

To illustrate this, check the below code example in which the dynamic h2 element is appended in the ngAfterViewInit lifecycle.

@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
styles: [`h2 {
color: red
}`]
})
export class App {
name:string; ele;
constructor(eleRef: ElementRef) {
this.name = `Angular! v${VERSION.full}`
this.ele = eleRef;
}
ngAfterViewInit() {
let dynam = document.createElement('h2');
dynam.innerHTML = 'Dynamic content ' + this.name;
this.ele.nativeElement.appendChild(dynam);
}
}

The result will be as follow, you can see that the style from the component is not applied to the dynamically inserted h2 element.

Dynamic element insertion — style is not applied

Shadow piercing descendant selector to the rescue

To resolve the above depicted problem, you can use the shadow piercing descendant selector. It is a technique introduced in shadow DOM concept which is deprecated in major browsers.

But you can use this in Angular using the ::ng-deep special selector. This selector will apply the parent component styles to the descendant child components.

The encapsulation mode should be Emulated to use this feature in Angular.

Now the component style should be modified as follows

::ng-deep h2 {
color: red
}

The result will be as follows

Dynamic element insertion — with ::ng-deep selector

Sample

https://plnkr.co/edit/qb9m0qglyDNzmizQkC9d?p=preview

Reference

  1. https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
  2. https://angular.io/guide/component-styles#view-encapsulation

--

--

Madhu Sudhanan
Madhu Sudhanan

Written by Madhu Sudhanan

Software developer and a blogger. Fond of Angular, React, Vue and Blazor frameworks. Follow me on Twitter — @maddydeep28. PortFolio — https://madhust.github.io/

Responses (1)