阻止来自影响父

时间:2017-07-14 16:24:22

标签: html css angular innerhtml

我创建了一个HTML电子邮件,可以在我测试的几个电子邮件客户端中正确显示,但是当我在我的页面上提供它的预览时,innerHTML中的嵌入式样式会影响父级。必须可以避免这种情况,因为当我在gmail中查看电子邮件时,它会正确显示,而不会改变gmail本身的风格。

这里有一些显示问题的HTML(但在gmail中没有副作用显示):

<!DOCTYPE HTML>
<html>
    <head>
        <style type="text/css">
            * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
        </style>
    </head>
    <body>
        <pre style="white-space:pre-wrap;">Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test </pre>
    </body>    
</html> 

我正在使用Angular 4,所以我将这种方式包含在我的网页中:

<div [innerHTML]="myHtml | safeHtml">
</div>

...而safeHtml只是绕过对我注入的HTML进行Angular检查的管道:

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

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
  constructor(private sanitizer:DomSanitizer){}

  transform(html) {

    return this.sanitizer.bypassSecurityTrustHtml(html);

  }
}

它有效,因为它确实在div中显示html,但样式信息会改变页面上的所有内容。我明白了 - 我在嵌入式样式中使用*。 ...但正如我所说,gmail设法包含&#39;这不知何故,所以它不会重新设置父元素。我该如何做到这一点?

理想情况下,我喜欢完全隔离风格 - 就像我不希望父级样式受到孩子的影响或父级影响受父母影响(看起来,这似乎是gmail的方式)表现得很好。

更新

将HTML更改为以下内容使其适用于电子邮件,并包含CSS,但没有嵌入Angular中工作:

<!DOCTYPE HTML>
<html class="my-class">
    <head>
        <style type="text/css">
            .my-class * { 
                font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 
                color: blue;
            }
            .my-class pre {
                white-space:pre-wrap;
            }
        </style>
    </head>
    <body>
        <pre>Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test </pre>
    </body>    
</html>   

这是因为(看起来)htmlbody标记在您将其嵌入div时会被删除(这有点意义)。所以,只需添加一个包含div的父级,这一切都有效 - 无论是嵌入式还是电子邮件:

<!DOCTYPE HTML>
<html>
    <head>
        <style type="text/css">
            .my-class * { 
                font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 
                color: blue;
            }
            .my-class pre {
                white-space:pre-wrap;
            }
        </style>
    </head>
    <body>
        <div class="my-class">
            <pre>Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test Test test </pre>
        </div>
    </body>    
</html> 

2 个答案:

答案 0 :(得分:2)

@ petryuno1建议的最佳方法是使用组件,因为它将CSS /样式范围仅限于该组件,但在基本级别,您可以将类应用于<div [innerHTML]="myHtml | safeHtml"></div>,例如:

<div class="foo" [innerHTML]="myHtml | safeHtml"></div>

如果某个组件不可用,那么修改css到目标类*

.foo * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }

无论class的修改如何,<div>上的innerHTML属性都会保留。

希望这有帮助!

答案 1 :(得分:0)

我发现使用Angular解决类似问题(必须在页面中显示电子邮件的HTML)的另一个解决方案是创建一个新组件以显示预览并将封装设置为ShadowDom。

  @Component({
  selector: 'app-email-view',
  templateUrl: './email-view.component.html',
  styleUrls: ['./email-view.component.scss'],
  encapsulation: ViewEncapsulation.ShadowDom
})
export class EmailViewComponent implements OnInit {

  @Input()
  preview: any;

在那之后,我只需在preview元素中插入[innerHtml]变量。

ShadowDom负责封装Style,而不让它影响其他组件。有关更多信息,您可以检查here