使用Web组件和CSS自定义属性的风格状态
Web组件为构建可重用的Web UI提供了一个很好的方法,无论它们在什么框架下使用,都可以在项目之间共享。Web组件通常利用Shadow DOM来提供CSS封装,以确保样式只应用于组件的模板。
当使用Shadow DOM时,样式被完全封装,防止全局或模板内的意外样式。使用CSS自定义属性,我们可以为我们如何启用或允许我们的可重用组件被定制而创建公共API。CSS自定义属性还提供了一个很好的方法来维护可能有几种不同视觉状态的组件的样式。
这篇文章将介绍一个用Lit构建的简单的警报Web组件。这个无状态的Web组件有几个我们想要表现的视觉变体。

这个警报组件有几种状态的颜色和两种大小的选择,默认和紧凑。我们可以通过我们组件上的属性/特性来表示这些状态。
<ui-alert>default alert</ui-alert>
<ui-alert status="success">success alert</ui-alert>
<ui-alert status="info">info alert</ui-alert>
<ui-alert status="danger">danger alert</ui-alert>
在我们的CSS中,我们可以定义我们警报的默认外观和感觉。这个组件的模板相对简单,只有一个slot ,将用户内容投射到我们的模板中。
<section>
<slot></slot>
</section>
在CSS中,我们为部分元素设置了样式;然而,我们为少数样式使用了CSS自定义属性。
:host {
--color: #fff;
--background: #6d6f74;
--padding: 16px;
--border-radius: 4px;
--font-size: 16px;
}
section {
border-radius: var(--border-radius);
background: var(--background);
padding: var(--padding);
color: var(--color);
font-size: var(--font-size);
display: flex;
align-items: center;
}
这几个属性是特别选择的,因为它们代表了在我们的各种视觉状态下变化的属性。我们可以使用CSS: host 选择器根据元素的状态来改变这些属性。
:host([status=info]) {
--background: #3665c2;
--color: #fff;
}
:host([status=success]) {
--background: #298338;
--color: #fff;
}
:host([status=danger]) {
--background: #c21919;
--color: #fff;
}
如果我们想添加我们的紧凑型警报,我们可以遵循同样的模式:
<ui-alert size="compact">default alert</ui-alert>
<ui-alert size="compact" status="success">success alert</ui-alert>
<ui-alert size="compact" status="info">info alert</ui-alert>
<ui-alert size="compact" status="danger">danger alert</ui-alert>

:host([size=compact]) {
--padding: 8px 12px;
--font-size: 14px;
}
通过这种方法,我们只需定义一次我们组件的外观和感觉。然后利用CSS自定义属性,我们为新的视觉状态的组件做 "主题"。
/* public CSS API */
:host {
--color: #fff;
--background: #6d6f74;
--padding: 16px;
--border-radius: 4px;
--font-size: 16px;
}
/* internal element styles */
section {
border-radius: var(--border-radius);
background: var(--background);
padding: var(--padding);
color: var(--color);
font-size: var(--font-size);
display: flex;
align-items: center;
}
/* element states */
:host([status=info]) {
--background: #3665c2;
--color: #fff;
}
:host([status=success]) {
--background: #298338;
--color: #fff;
}
:host([status=danger]) {
--background: #c21919;
--color: #fff;
}
:host([size=compact]) {
--padding: 8px 12px;
--font-size: 14px;
}
通过这种模式,我们还可以为消费者提供未来的定制服务。通过利用基于状态的属性,消费者可以用相同的API创建他们自己的自定义样式状态。
<ui-alert status="promotion">product alert</ui-alert>
ui-alert[status=promotion] {
--background: purple;
--color: gray;
}
通过一次定义组件的外观,我们可以确保在我们的元素内有易于使用的样式API和易于维护的样式。请在下面的链接中查看完整的演示!