Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - innerHTML styling

People also ask

How do you add a style to innerHTML?

Within HTML elements, there are three ways you can insert CSS into an HTML document. Inline – to use an inline style attribute. – within the /head/ section using an *style].

Can I use innerHTML in angular?

Angular 2+ supports an [innerHTML] property binding that will render HTML. If you were to otherwise use interpolation, it would be treated as a string. In this article, you will be presented with how to use [innerHTML] and some considerations for usage.

How do I display HTML inside an angular binding?

To add HTML that contains Angular-specific markup (property or value binding, components, directives, pipes, ...) it is required to add the dynamic module and compile components at runtime. This answer provides more details How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

Is it good practice to use innerHTML?

The use of innerHTML creates a potential security risk for your website. Malicious users can use cross-site scripting (XSS) to add malicious client-side scripts that steal private user information stored in session cookies. You can read the MDN documentation on innerHTML .


update 2 ::slotted

::slotted is now supported by all new browsers and can be used with ViewEncapsulation.ShadowDom

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

update 1 ::ng-deep

/deep/ was deprecated and replaced by ::ng-deep.

::ng-deep is also already marked deprecated, but there is no replacement available yet.

When ViewEncapsulation.Native is properly supported by all browsers and supports styling accross shadow DOM boundaries, ::ng-deep will probably be discontinued.

original

Angular adds all kinds of CSS classes to the HTML it adds to the DOM to emulate shadow DOM CSS encapsulation to prevent styles of bleeding in and out of components. Angular also rewrites the CSS you add to match these added classes. For HTML added using [innerHTML] these classes are not added and the rewritten CSS doesn't match.

As a workaround try

  • for CSS added to the component
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • for CSS added to index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>> (and the equivalent/deep/ but /deep/ works better with SASS) and ::shadow were added in 2.0.0-beta.10. They are similar to the shadow DOM CSS combinators (which are deprecated) and only work with encapsulation: ViewEncapsulation.Emulated which is the default in Angular2. They probably also work with ViewEncapsulation.None but are then only ignored because they are not necessary. These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.

Another approach is to use

@Component({
  ...
  encapsulation: ViewEncapsulation.None,
})

for all components that block your CSS (depends on where you add the CSS and where the HTML is that you want to style - might be all components in your application)

Update

Example Plunker


The simple solution you need to follow is

import { DomSanitizer } from '@angular/platform-browser';

constructor(private sanitizer: DomSanitizer){}

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}

We pull in content frequently from our CMS as [innerHTML]="content.title". We place the necessary classes in the application's root styles.scss file rather than in the component's scss file. Our CMS purposely strips out in-line styles so we must have prepared classes that the author can use in their content. Remember using {{content.title}} in the template will not render html from the content.


If you're trying to style dynamically added HTML elements inside an Angular component, this might be helpful:

// inside component class...
    
constructor(private hostRef: ElementRef) { }
    
getContentAttr(): string {
  const attrs = this.hostRef.nativeElement.attributes
  for (let i = 0, l = attrs.length; i < l; i++) {
    if (attrs[i].name.startsWith('_nghost-c')) {
      return `_ngcontent-c${attrs[i].name.substring(9)}`
    }
  }
}
    
ngAfterViewInit() {
  // dynamically add HTML element
  dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}

My guess is that the convention for this attribute is not guaranteed to be stable between versions of Angular, so that one might run into problems with this solution when upgrading to a new version of Angular (although, updating this solution would likely be trivial in that case).


The recommended version by Günter Zöchbauer works fine, but I have an addition to make. In my case I had an unstyled html-element and I did not know how to style it. Therefore I designed a pipe to add styling to it.

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';


@Pipe({
    name: 'StyleClass'
})
export class StyleClassPipe implements PipeTransform {

    constructor(private sanitizer: DomSanitizer) { }
    transform(html: any, styleSelector: any, styleValue: any): SafeHtml {
        const style = ` style = "${styleSelector}: ${styleValue};"`;
        const indexPosition = html.indexOf('>');
        const newHtml = [html.slice(0, indexPosition), style, html.slice(indexPosition)].join('');
        return this.sanitizer.bypassSecurityTrustHtml(newHtml);
    }

}

Then you can add style to any html-element like this:

<span [innerhtml]="Variable | StyleClass: 'margin': '0'"> </span>

With:

Variable = '<p> Test </p>'

Use the below method to allow CSS styles in innerhtml.

import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
.
.
.
.
html: SafeHtml;

constructor(protected _sanitizer: DomSanitizer) {
   this.html = this._sanitizer.bypassSecurityTrustHtml(`
        <html>
        <head></head>
        <body>
           <div style="display:flex; color: blue;">
              <div>
                 <h1>Hello World..!!!!!</h1>
              </div>
           </div>
        </body>
        </html>`);
}

Example code stackblitz

Or use the below method to write directly in HTML. https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1