将开槽样式优先于全局样式
Prioritizing slotted styling over global styling
假设我有一个应用程序,默认情况下段落为红色,但我想使用自定义元素(我们称之为 <blue-stuff>
)将某些段落设置为蓝色和粗体。在下面的代码片段中,我尝试使用 Web 组件和阴影 dom 执行此操作,依赖于 ::slotted
伪元素:
customElements.define('blue-stuff', class extends HTMLElement {
constructor() {
super()
.attachShadow({ mode: 'open' })
.appendChild(document.importNode(document.getElementById('blue-template').content, true))
}
})
p {
color: red;
}
<template id="blue-template">
<style>
.blue ::slotted(p) {
color: blue;
font-weight: bold;
}
</style>
<div class="blue">
<slot></slot>
</div>
</template>
<p>Hello I am red!</p>
<blue-stuff>
<p>Hello, I am supposed to be blue and bold!</p>
</blue-stuff>
令我惊讶的是,本应为蓝色的段落实际上是红色的,这意味着它优先考虑简单的 p
selector 而不是 .blue ::slotted(p)
selector .通常,特异性会解决这个问题,但在这种情况下,“光”样式 dom 比阴影 dom.
更受欢迎
问题:在我的示例中,是否可以将 <blue-stuff>
中的段落样式设置为蓝色而不使用 !important
?
目前想到的:
- 给每个不在组件中的段落命名为 class,并将其命名为
paragraph
,并改为 select。有点用力,而不是我想做的事情,因为我正在从 markdown 中解析这些段落。
- 将红色应用于 包裹 段落,因此
p
本身不再具有规则。虽然这适用于颜色等继承属性,但不适用于边距等属性。
- 通过 selecting
blue-stuff p { ... }
在灯光 DOM 中应用样式。可以用,但是现在感觉组件不能自给自足
我在 Firefox 中处理过这个问题。
你落入了<slot>
陷阱
长答案见:
一个。开槽元素反映在阴影DOM中,它未移动到阴影DOM<slot>
乙。开槽内容的样式来自容器(隐藏)lightDOM 元素定义在
在你的情况下,这是主要的 DOM
customElements.define('blue-stuff', class extends HTMLElement {
constructor() {
super()
.attachShadow({
mode: 'open'
})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = () => BLUE.disabled = !BLUE.disabled;
}
})
p {
color: red;
font-size: 20px;
font-family: Arial;
}
span {
background:gold;
}
<template id="BLUE-STUFF">
<style>
::slotted(p) {
color : blue; /* not applied because inheritable color:red */
font-weight: bold; /* applied, no inherited setting */
cursor: pointer; /* applied, no inherited setting */
font-family: Georgia !important; /* be a crap Designer, force it */
}
::slotted(span){
background:black !important;
/* won't work, ::slotted can only style lightDOM 'skin' (p) */
}
</style>
<slot></slot>
</template>
<style id=BLUE onload="this.disabled=true">/* click to toggle stylesheet */
blue-stuff p{
color:blue;
font-weight: normal;
font-family: Arial !important; /* not applied, fire that 'designer'! */
}
</style>
<blue-stuff>
<p>I <span>should</span> be styled by my container DOM [click me]</p>
</blue-stuff>
因为 A. 和 B. ::slotted()
不 对特异性有任何影响
与字体相关的 CSS 是 inheritable styles,滴入阴影DOM,
这就是 font-size
变成 20px
的原因
大多数 CSS 不会 滴入阴影 DOM,但 CSS-properties 会[=22] =]
应用了字体粗细,因为还没有定义字体粗细
强制你的蓝色的唯一方法是在 ::slotted 选择器中使用 !important
,
见 font-family
但是你的风格应该来自主 DOM:
blue-stuff p{
color:blue
}
假设我有一个应用程序,默认情况下段落为红色,但我想使用自定义元素(我们称之为 <blue-stuff>
)将某些段落设置为蓝色和粗体。在下面的代码片段中,我尝试使用 Web 组件和阴影 dom 执行此操作,依赖于 ::slotted
伪元素:
customElements.define('blue-stuff', class extends HTMLElement {
constructor() {
super()
.attachShadow({ mode: 'open' })
.appendChild(document.importNode(document.getElementById('blue-template').content, true))
}
})
p {
color: red;
}
<template id="blue-template">
<style>
.blue ::slotted(p) {
color: blue;
font-weight: bold;
}
</style>
<div class="blue">
<slot></slot>
</div>
</template>
<p>Hello I am red!</p>
<blue-stuff>
<p>Hello, I am supposed to be blue and bold!</p>
</blue-stuff>
令我惊讶的是,本应为蓝色的段落实际上是红色的,这意味着它优先考虑简单的 p
selector 而不是 .blue ::slotted(p)
selector .通常,特异性会解决这个问题,但在这种情况下,“光”样式 dom 比阴影 dom.
问题:在我的示例中,是否可以将 <blue-stuff>
中的段落样式设置为蓝色而不使用 !important
?
目前想到的:
- 给每个不在组件中的段落命名为 class,并将其命名为
paragraph
,并改为 select。有点用力,而不是我想做的事情,因为我正在从 markdown 中解析这些段落。 - 将红色应用于 包裹 段落,因此
p
本身不再具有规则。虽然这适用于颜色等继承属性,但不适用于边距等属性。 - 通过 selecting
blue-stuff p { ... }
在灯光 DOM 中应用样式。可以用,但是现在感觉组件不能自给自足
我在 Firefox 中处理过这个问题。
你落入了<slot>
陷阱
长答案见:
一个。开槽元素反映在阴影DOM中,它未移动到阴影DOM
<slot>
乙。开槽内容的样式来自容器(隐藏)lightDOM 元素定义在
在你的情况下,这是主要的 DOM
customElements.define('blue-stuff', class extends HTMLElement {
constructor() {
super()
.attachShadow({
mode: 'open'
})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = () => BLUE.disabled = !BLUE.disabled;
}
})
p {
color: red;
font-size: 20px;
font-family: Arial;
}
span {
background:gold;
}
<template id="BLUE-STUFF">
<style>
::slotted(p) {
color : blue; /* not applied because inheritable color:red */
font-weight: bold; /* applied, no inherited setting */
cursor: pointer; /* applied, no inherited setting */
font-family: Georgia !important; /* be a crap Designer, force it */
}
::slotted(span){
background:black !important;
/* won't work, ::slotted can only style lightDOM 'skin' (p) */
}
</style>
<slot></slot>
</template>
<style id=BLUE onload="this.disabled=true">/* click to toggle stylesheet */
blue-stuff p{
color:blue;
font-weight: normal;
font-family: Arial !important; /* not applied, fire that 'designer'! */
}
</style>
<blue-stuff>
<p>I <span>should</span> be styled by my container DOM [click me]</p>
</blue-stuff>
因为 A. 和 B.
::slotted()
不 对特异性有任何影响与字体相关的 CSS 是 inheritable styles,滴入阴影DOM,
这就是font-size
变成 20px
的原因 大多数 CSS 不会 滴入阴影 DOM,但 CSS-properties 会[=22] =]应用了字体粗细,因为还没有定义字体粗细
强制你的蓝色的唯一方法是在 ::slotted 选择器中使用
!important
,
见font-family
但是你的风格应该来自主 DOM:
blue-stuff p{
color:blue
}