PPK 在 “使用自定义属性的两种选择” 中阐述了一个有趣的情况,他与 Stefan Judis 对使用 自定义属性 做同样事情有两种不同的方法。 在一种方法中,链接的悬停和焦点样式使用两个不同的自定义属性处理,每个状态一个。 在另一种方法中,使用单个自定义属性。
两个自定义属性
.component1 {
--linkcolor: red;
--hovercolor: blue;
}
.component2 {
--linkcolor: purple;
--hovercolor: cyan;
}
a {
color: var(--linkcolor);
}
a:hover,a:focus {
color: var(--hovercolor)
}
一个自定义属性
.component1 a {
--componentcolor: red;
}
.component1 :is(a:hover,a:focus) {
--componentcolor: blue;
}
.component2 a {
--componentcolor: purple;
}
.component2 :is(a:hover,a:focus) {
--componentcolor: cyan;
}
a {
color: var(--componentcolor)
}
使用两个属性有一种更自然的感觉,就像它非常明确地说明了特定自定义属性的用途。 但使用一个自定义属性有很多优点。 不仅是为了减少一个自定义属性,而且自定义属性与单个属性一一对应。
进一步来看,您可以使用一个规则集,每个属性一个自定义属性,为更改内容提供一种类似于“菜单”的选项。 PPK 对此说道:
现在您本质上找到了一个定义文件。 您不仅看到了组件的默认样式,还看到了可能发生变化和不会发生变化的内容。
也就是说,您可以为要更改的任何内容使用自定义属性,而对于不想更改的任何内容,您则不会使用。 这当然是一种有趣的方法,我不会怪任何尝试的人。
.lil-grid {
/* will change */
--padding: 1rem;
padding: var(--padding);
--grid-template-columns: 1fr 1fr 1fr;
grid-columns: var(--grid-template-columns);
/* won't change */
border: 1px solid #ccc;
gap: 1rem;
}
我对这种方法的犹豫是,它充其量只是一个提示,表明哪些内容会发生变化,哪些内容不会发生变化。 例如,即使在自定义属性中未设置内容,我仍然可以更改内容。 之后,我可以执行以下操作:
.lil-grid.two-up {
grid-columns: 1fr 1fr;
}
这会消除自定义属性的使用。 同样,我永远无法更改 --grid-template-columns
的值,这意味着它看起来会在不同的情况下发生变化,但实际上从未发生变化。
同样,我可以执行以下操作:
.lil-grid.thick {
border-width: 3px;
}
… 即使我最初的组件规则集暗示边框宽度不会发生变化,但它会使用修饰符类发生变化。
因此,为了使这种方法有效,您需要将其视为一种坚持的约定,类似于通用的编码标准。 不过,我担心这会变成一件麻烦事。 对于您决定更改的任何声明,您都必须返回并进行重构,使其成为或不成为自定义属性。
这使我想到了 HTML 和 CSS 的“隐式样式 API”。 我们已经在浏览器中拥有一个样式 API。 HTML 在浏览器中转换为 DOM,我们使用 CSS 对 DOM 进行样式设置。 选择内容,对其进行样式设置。
也许我们不需要一个菜单来显示可以和不可以设置样式的内容,因为 DOM 和 CSS 本身就是这样的。 这并不是说精心制作的自定义属性集不能成为其中的一部分,但它们不需要代表更改和不更改内容的硬性规则。
说到隐式样式 API,Jim Nielsen 在 “Shadow DOM 及其对非官方样式 API 的影响” 中写道:
[…] shadow DOM 破坏了我们多年来在网络上使用的自文档样式 API。
什么样式 API? 如果您想为屏幕上的元素设置样式,您可以打开开发者工具,查看 DOM,找到您想要的元素,找出目标该元素的正确选择器,编写选择器和样式,就完成了。
如果您停下来思考一下,这真是太了不起了。
我想这就是我对 Web 组件最大的不满。 我并不讨厌 Shadow DOM; 事实上,它可能是我最喜欢的 Web 组件方面。 我只是不喜欢我必须为它们发明一个样式 API(类似于内部摆动的自定义属性或 ::part
),而不是使用一直为我们服务良好的样式 API:DOM + CSS。
我所共鸣的是“现在您本质上找到了一个定义文件”。
这让我想到,哦,这是一个放置设计系统令牌的地方。 任何字体、颜色、间距等等,这些内容可能会在一个组件内发生变化,或在多个组件之间使用。