You are currently viewing Making Styles Work with [innerHtml] in Angular
Angular

Making Styles Work with [innerHtml] in Angular

In this post, we’ll look at how we can apply styles to html content rendered via innerHtml attribute.

By default, styles defined in an Angular component only work in that specific component. This is due to the Emulated view encapsulation policy set by Angular.

This logical scope is great because styles of component A cannot affect component B. This is also the case where component B is a child of component A.

Example

In the following template, we want to apply styling the img tag in the html content.

const content = '<img src=".." alt="..">'

<!-- Post page component html -->
<div [innerHtml]="content"></div>Code language: HTML, XML (xml)

Unfortunately, the following CSS rule does not work because of the default view encapsulation policy.

img {
    border: 1px solid red !important;
}Code language: CSS (css)

Emulated view encapsulation is preventing styles from intercepting inside and outside of the component.

In this case, value bound to innerHtml attribute is considered outside of the component. This is because the value of content variable was not originally defined in your component HTML.

There are a couple of ways you can work around this issue. Let’s check out each solution.

Remove view encapsulation

#1 workaround is to change the view encapsulation of the component to ViewEncapsulation.None

@Component({
  selector: 'app-post-page',
  templateUrl: './post-page.component.html',
  styleUrls: ['./post-page.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class PostPageComponent implements OnInit {}
Code language: TypeScript (typescript)

Please note that changing ViewEncapsulation to None can have pretty far-reaching consequences.

This applies your styles globally – so if you set something like a div tag to have a background color, this will change all divs in your app to have that background color.

I would steer clear of changing the ViewEncapsulation unless you absolutely have to.

Use ::ng-deep

A better solution is to use ::ng-deep selector in each of your CSS rules.

:host ::ng-deep img {
    border: 1px solid red !important;
}Code language: CSS (css)

This styling above will now apply to images deep in this component.

It is important to limit the use of ::ng-deep to only children of an encapsulated parent component. Otherwise, it would apply to all images in child components.

Using the :host keyword before ::ng-deep takes care of this.

Umut Esen

I am a software developer and blogger with a passion for the world wide web.

Leave a Reply