166

I am passing html as innerHtml to my view. Below is my view

<div [innerHTML]="someHtmlCode"></div>

if I pass the below code, it is working fine.

this.someHtmlCode = "<div><b>This is my HTML.</b></div>"

if I pass the below code which contains color, it is not working.

 this.someHtmlCode = '<div style="background-color: blue;"><b>This is my HTML.</b></div>';
Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
Chatra
  • 2,989
  • 7
  • 40
  • 73
  • 3
    https://medium.com/@ahmedhamedTN/make-styles-work-when-dealing-with-innerhtml-in-angular-ac2d524ba001 use this.... – SuReSh Jun 10 '19 at 05:21
  • 4
    https://stackoverflow.com/questions/39628007/angular2-innerhtml-binding-remove-style-attribute/39630507#39630507 this may help you. – Neenu Chandran Dec 11 '19 at 11:47
  • Check this ideal use case for styles: https://angular.io/api/platform-browser/DomSanitizer#bypassSecurityTrustStyle – Marian07 Jan 03 '23 at 17:26

3 Answers3

322

This behavior you're getting is normal. The class added to innerHTML is ignored because by default the encapsulation is Emulated. Which means Angular prevents styles from intercepting inside and outside of the component. You should change the encapsulation to None in your component. This way, you'll be able to define classes wherever you want: inside styles or in a separate .css, .scss or .less style-sheet (it doesn't matter) and Angular will add them to the DOM automatically.

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

@Component({
  selector: 'example',
  styles: ['.demo {background-color: blue}'],
  template: '<div [innerHTML]="someHtmlCode"></div>',
  encapsulation: ViewEncapsulation.None,
})
export class Example {
  private someHtmlCode = '';

  constructor() {
    this.someHtmlCode = '<div class="demo"><b>This is my HTML.</b></div>';
  }
}
Unsinkable Sam
  • 3,809
  • 1
  • 10
  • 18
  • 26
    If I pass just style without class It is not working – Chatra May 27 '17 at 13:27
  • 2
    You're right and I couldn't find a solution to make it work :) I would advise you however not to use inlined styles as it is not a good practice to have it mixed within the template. – Unsinkable Sam May 27 '17 at 16:39
  • 4
    @Chatra You may want to check out [this](https://angular.io/api/platform-browser/DomSanitizer) – DongBin Kim Apr 10 '18 at 02:26
  • 10
    `ViewEncapsulation` is a part of angular/core: `import { ViewEncapsulation } from '@angular/core';` – Wiil Sep 26 '18 at 20:55
  • 3
    Make sure you import ViewEncapsulation from @angular/core and NOT from @angular/compiler/src/core. Otherwise, you will end up with a mysterious error - "Cannot find module 'tslib'"! – Alphonso Nov 21 '18 at 11:45
  • 3
    Ohh my God, you're an incarnation. I've been scratching my head on this problem for two days. Thank you very much. – Sanjay Verma Feb 09 '19 at 17:37
  • I get `core.js:1633 ERROR cordova_not_available` in browser, after adding the import of `{ViewEncapsulation} from '@angular/core';` – farahm Apr 24 '20 at 16:03
  • 2
    You can also use:host ::ng-deep or only ::ng-deep to apply style. You need to declare these modifiers in the style file. – Jeet Feb 25 '21 at 14:20
  • 14
    It's worth noting 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. – Jason Long Mar 17 '21 at 15:55
  • i have same error. but the content is being fetch from database with inline style. so how can i solve this. – azhar May 02 '21 at 02:21
  • 1
    The question is about using explicit inline styles, not classes. – Nikola Diklich Jul 21 '21 at 14:25
  • 1
    Any solution without viewEncapsulation.None? – Leonardo Rick Feb 21 '22 at 21:03
  • We can also use `::ng-deep` in the styles file, this will do the job without specifying `ViewEncapsulation.None` (i.e. ViewEncapsulation staying on `Emulated` which is the default one). Ex: (in component's scss file:) `::ng-deep .demo {color: red}` – nikola3103 Mar 01 '23 at 01:12
  • Making Angular component encapsulation none is not good idea. adding CSS class to the global CSS file (it should register in Angular.json) will work perfectly – Amila Thennakoon Aug 15 '23 at 11:10
48

I was also facing the same issue but after reading this below link I figured out the solution and it was done without using pipes

Hope this will help you.

https://netbasal.com/angular-2-security-the-domsanitizer-service-2202c83bd90

Shehram Tahir
  • 915
  • 2
  • 9
  • 19
  • 1
    this is the right answer by the way, i was pulling html content from google api gmail messages, which contains inline styling and there's no way around that. Using this solution i managed to actually display the content of emails in the same way that gmail displays them, wish i could give u a +200, saved my day – WtFudgE Apr 15 '20 at 13:32
  • 1
    It is not @WtFudgE. One thing is injecting HTML that, yes, you need/should sanitize it using a pipe, and another thing is, once the code is injected through [innerHTML], having the ability to style it through component's style sheet. Which you can't - it's a bug assumed by Angular many years ago, and not dealt with properly. So... to style it, you do need to get ride of component's encapsulation, by `encapsulation: ViewEncapsulation.None` – Pedro Ferreira May 10 '20 at 15:30
  • 17
    Thanks. I had a similar problem using code for innerHTML created by quill editor. Disabling ViewEncapulation won't work for every attributes like style e.g. - so you can use `
    ` and add it to the constructor `public sanitizer: DomSanitizer` Of course beware of XSS!!!
    – René Preisler Nov 24 '20 at 18:04
  • I wasn't able to get this method to recognize css variables, ie `var(--blue)` – cs_pupil Apr 16 '21 at 23:35
  • @RenéPreisler Thanks this has worked for me I am using Vue2-editor in my admin and adding this in my angular app helped me to add colors as its a style attribute – Fabian Dec 20 '22 at 09:38
-3

Instead of an inline style, I put the style in a class.

Not sure if using class is an option for you or not, but here's a Plunker demo.

HTML:

this.someHtmlCode = '<div class="demo"><b>This is my HTML.</b></div>'

Define the class demo at the global root css file, usually it's called styles.scss.

CSS:

.demo{
    background-color: blue;
}
Nehal
  • 13,130
  • 4
  • 43
  • 59
  • it is not working, Is there any difference if my demo css is in less file? – Chatra May 27 '17 at 02:23
  • This works if the css is in the global styles.css file, but not in a non-global css file. It would be helpful if someone could explain the difference, but in the meantime I thought I'd post a comment to make others aware that getting this working depends on such details. – Mickey Segal Mar 09 '18 at 14:49
  • 1
    my-angular-component.html has `
    " (click)="handleStaticClick($event)"` ... then in my-angular-component.css use `.my-static-div ::ng-deep .my-dynamic-div { color: blue; }` and my-angular-component.ts `public handleStaticClick(event) { if (event.srcElement.classList.contains('my-dynamic-div')) { this.handleDynamicClick(); }}`
    – Michelle Norris Jan 31 '19 at 15:14
  • 3
    I solved my issue with this awnser by placing the selector ::ng-deep before the class. – user3466681 Feb 19 '20 at 16:52
  • Actually I solved my problem doing this. I defined a class `.mono { font-family: monospace !important; }` in my `style.scss` and then used it as usual: `

    Title

    `
    – Martinocom Apr 12 '22 at 10:11