首页 > 解决方案 > ShadyCSS polyfill 无法正确处理 Edge 中的 CSS

问题描述

我正在为第三方网站构建一个小部件,使用影子 DOM 来防止他们的 CSS 干扰我们的。我正在使用ShadyDOMShadyCSS polyfill使其在 Edge 和 IE 中工作,但它并没有像我期望的那样为 shadow DOM 转换 CSS。

例子:

<!DOCTYPE html>
<html>
	<head>
		<title>Shadow DOM test</title>
	</head>
	<body>
		<div id="container">container is here</div>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>
		<script>
			const shadow = document.getElementById("container").attachShadow({ mode: "open" });
			const style = document.createElement("style");
			style.innerHTML = `
				:host .stuff {
					background: #ff00ff;
				}
			`;
			shadow.appendChild(style);
			const div = document.createElement("div");
			div.classList.add("stuff");
			div.innerHTML = "stuff inside shadow dom";
			shadow.appendChild(div);
		</script>
	</body>
</html>

在 Chrome(原生支持 shadow DOM)中,stuffdiv 有粉红色背景,正如我所料。但是在 Edge(它本身不支持 shadow DOM)中,我看到了“shadow dom 内的东西”文本(意味着我的脚本运行并且 ShadyDOM 函数有效),但我没有看到粉红色的背景。

为什么会这样?我将影子根附加到一个普通的旧 div,而不是像 ShadyCSS README 中的示例那样使用自定义元素,但这有关系吗?如果是这样,我怎样才能使这项工作?我正在开发一个大型的现有应用程序,并且不想一次进行太多更改,因此我强烈希望使用我已经在使用的标准 HTML 元素(divs、buttons 等),而不是想出我的自己的元素或模板,尽管如果可以轻松完成,我愿意考虑模板和/或自定义元素,而不必进行很多大的更改。

标签: javascriptweb-componentshadow-dompolyfillsshady-dom

解决方案


使用 ShadyCSS

:hostCSS 伪元素在 Edge 中是未知的。

为了使其工作,您应该使用ShadyCSS.prepareTemplate()它将 :host 替换为自定义元素的名称,并将样式定义为将应用于所有页面的全局样式。

请记住,Edge 中没有 Shadow DOM:对于带有虚假/填充的 Shadow DOM 的 CSS 没有边界/范围。

在您的情况下,您可以使用ShadyCSS.prepareTemplate( yourTemplate, 'div' )以下示例:

ShadyCSS.prepareTemplate( tpl, 'div' )
container.attachShadow( { mode: "open" } )
         .appendChild( tpl.content.cloneNode(true) )
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>

<template id=tpl>
    <style>
    :host .stuff {
       background: #ff00ff;
     }
     </style>
    <div class=stuff>stuff inside shadow dom</div>
</template>

<div id=container>container is here</div>

注意:由于 polyfill 将 :host 替换为 div 并将其添加为全局样式,如果您有另一个匹配的 HTML 代码部分,您可能会观察到一些副作用div .stuff


没有 ShadyCSS

ShadyCSS 是为自定义元素设计的,但并不是真正为标准元素设计的。但是,您应该从 polyfill 中获得灵感,并为假(polyfill)Shadow DOM 显式创建样式属性。在您的情况下替换:hostdiv#containter

container.attachShadow( { mode: "open" } )
         .appendChild( tpl.content.cloneNode(true) )
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.3.0/webcomponents-bundle.js"></script>

<template id=tpl>
    <style>
    div#container .stuff { 
       background: #ff00ff;
     }    
    :host .stuff {
       background: #ff00ff;
     }
     </style>
    <div class=stuff>stuff inside shadow dom</div>
</template>

<div id=container>container is here</div>


推荐阅读