|
给 Shadow DOM 添加样式
shadow DOM 可以包含 <style> 和 <link rel="stylesheet" href="…"> 标签。在后一种情况下,样式表是 HTTP 缓存的,因此不会为使用同一模板的多个组件重新下载样式表。
一般来说,局部样式只在 shadow 树内起作用,文档样式在 shadow 树外起作用。但也有少数例外。
:host
:host 选择器允许选择 shadow 宿主(包含 shadow 树的元素)。
例如,我们正在创建 <custom-dialog> 元素,并且想使它居中。为此,我们需要对 <custom-dialog> 元素本身设置样式。
这正是 :host 所能做的:
<template id="tmpl">
<style>
/* 这些样式将从内部应用到 custom-dialog 元素上 */
:host {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: inline-block;
border: 1px solid red;
padding: 10px;
}
</style>
<slot></slot>
</template>
<script>
customElements.define('custom-dialog', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'}).append(tmpl.content.cloneNode(true));
}
});
</script>
<custom-dialog>
Hello!
</custom-dialog>
级联
shadow 宿主( <custom-dialog> 本身)驻留在 light DOM 中,因此它受到文档 CSS 规则的影响。
如果在局部的 :host 和文档中都给一个属性设置样式,那么文档样式优先。
例如,如果在文档中我们有如下样式:
<style>
custom-dialog {
padding: 0;
}
</style>
……那么 <custom-dialog> 将没有 padding。
这是非常有利的,因为我们可以在其 :host 规则中设置 “默认” 组件样式,然后在文档中轻松地覆盖它们。
唯一的例外是当局部属性被标记 !important 时,对于这样的属性,局部样式优先。
:host(selector)
与 :host 相同,但仅在 shadow 宿主与 selector 匹配时才应用样式。
例如,我们希望仅当 <custom-dialog> 具有 centered 属性时才将其居中:
<template id="tmpl">
<style>
:host([centered]) {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-color: blue;
}
:host {
display: inline-block;
border: 1px solid red;
padding: 10px;
}
</style>
<slot></slot>
</template>
<script>
customElements.define('custom-dialog', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'}).append(tmpl.content.cloneNode(true));
}
});
</script>
<custom-dialog centered>
Centered!
</custom-dialog>
<custom-dialog>
Not centered.
</custom-dialog>
现在附加的居中样式只应用于第一个对话框:<custom-dialog centered>。
:host-context(selector)
与 :host 相同,但仅当外部文档中的 shadow 宿主或它的任何祖先节点与 selector 匹配时才应用样式。
例如,:host-context(.dark-theme) 只有在 <custom-dialog> 或者 <custom-dialog> 的任何祖先节点上有 dark-theme 类时才匹配:
<body class="dark-theme">
<!--
:host-context(.dark-theme) 只应用于 .dark-theme 内部的 custom-dialog
-->
<custom-dialog>...</custom-dialog>
</body>
总之,我们可以使用 :host-family 系列的选择器来对组件的主元素进行样式设置,具体取决于上下文。这些样式(除 !important 外)可以被文档样式覆盖。
|
|