WebComponents - 在组件 Public 界面中使用 CSS 自定义属性有什么好处?
WebComponents - what's the advantage of using CSS Custom Properties in the Component Public Interface?
WebComponent
可能在其封装样式中包含 CSS 自定义属性。
这为组件的消费者提供了一种自定义组件样式的方法:
声明中
--fancy-tabs-bg: red
在主要样式中表示当shadow-root
样式包含
background-color: var(--fancy-tabs-bg, #9E9E9E)
background-color
将是 red
(或 --fancy-tabs-bg
设置的任何值)。
但是... 我在同一篇文章中注意到它明确指出:
One gotcha with :host
is that rules in the parent page have higher
specificity than :host
rules defined in the element. That is,
outside styles win. This allows users to override your top-level
styling from the outside.
再一次,稍后:
Outside styles always win over styles defined in shadow DOM. For example, if the user writes the selector fancy-tabs { width: 500px; }
, it will trump the component's rule: :host { width: 650px;}
所以...而不是为 --fancy-tabs-bg
声明一个值,我们可以...为 background-color
设置一个值 (?)
真的吗?让我们一探究竟。
这是一个 WebComponent
(主要是从上面引用的文章中复制的),其中组件的前两个实例使用 CSS 自定义 属性(即 --fancy-tabs-bg
),第三个实例直接设置样式,使用相关的 CSS 属性(即 background-color
).
class FancyTabs extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: "open"});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: block;
width: 100px;
height: 100px;
margin: 6px;
border-radius: 10px;
}
:host([background]) {
background-color: var(--fancy-tabs-bg, #9E9E9E);
}
</style>
`;
}
}
customElements.define('fancy-tabs', FancyTabs);
fancy-tabs {
float: left;
}
fancy-tabs:nth-of-type(1) {
--fancy-tabs-bg: red;
}
fancy-tabs:nth-of-type(2) {
--fancy-tabs-bg: orange;
}
fancy-tabs:nth-of-type(3) {
background-color: green;
}
<fancy-tabs background>...</fancy-tabs>
<fancy-tabs background>...</fancy-tabs>
<fancy-tabs background>...</fancy-tabs>
没有区别,是吗?
那么为什么要使用 CSS 自定义属性?为什么要在 public 界面中突出显示特定的 CSS 属性 可用于用户自定义?当然 所有 CSS 属性都可用于用户自定义,不是吗?
我错过了什么?
在处理宿主元素时您不会注意到任何差异,但是当内部有更多元素时您可以清楚地看到 CSS 变量的使用:
示例,其中 CSS 变量可用于更新嵌套元素的样式。我怀疑你能否在没有 CSS 变量的情况下找到更好的方法。
class FancyTabs extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host {
display: block;
width: 100px;
height: 100px;
margin: 6px;
border-radius: 10px;
}
:host([background]) {
background-color: var(--fancy-tabs-bg, #9E9E9E);
}
div {
padding: var(--p,0px);
border:var(--b,0px) solid;
}`
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = this.innerHTML;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
customElements.define('fancy-tabs', FancyTabs);
fancy-tabs {
float: left;
}
fancy-tabs:nth-of-type(1) {
--fancy-tabs-bg: red;
--p:20px;
--b:5px;
}
fancy-tabs:nth-of-type(2) {
--fancy-tabs-bg: orange;
--p:10px;
--b:3px;
}
fancy-tabs:nth-of-type(3) {
--fancy-tabs-bg: orange;
padding:20px; /* will get applied to host*/
border-width:5px; /* will do nothing */
}
<fancy-tabs background>text here</fancy-tabs>
<fancy-tabs background>text here</fancy-tabs>
<fancy-tabs background>text here</fancy-tabs>
WebComponent
可能在其封装样式中包含 CSS 自定义属性。
这为组件的消费者提供了一种自定义组件样式的方法:
声明中
--fancy-tabs-bg: red
在主要样式中表示当shadow-root
样式包含
background-color: var(--fancy-tabs-bg, #9E9E9E)
background-color
将是 red
(或 --fancy-tabs-bg
设置的任何值)。
但是... 我在同一篇文章中注意到它明确指出:
One gotcha with
:host
is that rules in the parent page have higher specificity than:host
rules defined in the element. That is, outside styles win. This allows users to override your top-level styling from the outside.
再一次,稍后:
Outside styles always win over styles defined in shadow DOM. For example, if the user writes the selector
fancy-tabs { width: 500px; }
, it will trump the component's rule::host { width: 650px;}
所以...而不是为 --fancy-tabs-bg
声明一个值,我们可以...为 background-color
设置一个值 (?)
真的吗?让我们一探究竟。
这是一个 WebComponent
(主要是从上面引用的文章中复制的),其中组件的前两个实例使用 CSS 自定义 属性(即 --fancy-tabs-bg
),第三个实例直接设置样式,使用相关的 CSS 属性(即 background-color
).
class FancyTabs extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: "open"});
}
connectedCallback() {
this.root.innerHTML = `
<style>
:host {
display: block;
width: 100px;
height: 100px;
margin: 6px;
border-radius: 10px;
}
:host([background]) {
background-color: var(--fancy-tabs-bg, #9E9E9E);
}
</style>
`;
}
}
customElements.define('fancy-tabs', FancyTabs);
fancy-tabs {
float: left;
}
fancy-tabs:nth-of-type(1) {
--fancy-tabs-bg: red;
}
fancy-tabs:nth-of-type(2) {
--fancy-tabs-bg: orange;
}
fancy-tabs:nth-of-type(3) {
background-color: green;
}
<fancy-tabs background>...</fancy-tabs>
<fancy-tabs background>...</fancy-tabs>
<fancy-tabs background>...</fancy-tabs>
没有区别,是吗?
那么为什么要使用 CSS 自定义属性?为什么要在 public 界面中突出显示特定的 CSS 属性 可用于用户自定义?当然 所有 CSS 属性都可用于用户自定义,不是吗?
我错过了什么?
在处理宿主元素时您不会注意到任何差异,但是当内部有更多元素时您可以清楚地看到 CSS 变量的使用:
示例,其中 CSS 变量可用于更新嵌套元素的样式。我怀疑你能否在没有 CSS 变量的情况下找到更好的方法。
class FancyTabs extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'closed' });
const css = `
:host {
display: block;
width: 100px;
height: 100px;
margin: 6px;
border-radius: 10px;
}
:host([background]) {
background-color: var(--fancy-tabs-bg, #9E9E9E);
}
div {
padding: var(--p,0px);
border:var(--b,0px) solid;
}`
this.styles = document.createElement('style');
this.styles.innerHTML = css;
}
connectedCallback() {
const div = document.createElement('div');
div.innerHTML = this.innerHTML;
this.shadow.appendChild(this.styles);
this.shadow.appendChild(div);
}
}
customElements.define('fancy-tabs', FancyTabs);
fancy-tabs {
float: left;
}
fancy-tabs:nth-of-type(1) {
--fancy-tabs-bg: red;
--p:20px;
--b:5px;
}
fancy-tabs:nth-of-type(2) {
--fancy-tabs-bg: orange;
--p:10px;
--b:3px;
}
fancy-tabs:nth-of-type(3) {
--fancy-tabs-bg: orange;
padding:20px; /* will get applied to host*/
border-width:5px; /* will do nothing */
}
<fancy-tabs background>text here</fancy-tabs>
<fancy-tabs background>text here</fancy-tabs>
<fancy-tabs background>text here</fancy-tabs>