借助 Houdini 的新 API 实现更智能的自定义属性

CSS 中的转换和数据保护

借助 CSS 自定义属性(也称为 CSS 变量),您可以在 CSS 中定义自己的属性,并在整个 CSS 中使用其值。虽然它们目前非常有用,但也存在一些缺点,可能会导致它们难以使用:它们可以接受任何值,因此可能会意外被意外内容覆盖,它们始终从父项继承值,并且您无法对其进行转换。现在,Chrome 78 中提供 Houdini 的 CSS Properties and Values API Level 1,这些缺点已得到克服,CSS 自定义属性变得非常强大!

什么是 Houdini?

在讨论新 API 之前,我们先快速介绍一下 Houdini。CSS-TAG Houdini 工作组(也称为 CSS Houdini,或简称 Houdini)的目标是“开发可解释 Web 上样式和布局‘魔法’的功能”。这组 Houdini 规范旨在充分发挥浏览器渲染引擎的强大功能,让您能够更深入地了解我们的样式,并能够扩展我们的渲染引擎。这样一来,我们终于可以使用 JavaScript 中的类型化 CSS 值,并在不影响性能的情况下实现 polyfill 或发明新的 CSS。Houdini 有望为 Web 上的创意注入强大动力。

CSS 属性和值 API 级别 1

借助 CSS Properties and Values API Level 1(Houdini Props and Vals),我们可以为自定义属性提供结构。使用自定义属性时,目前的情况如下:

.thing {
  --my-color: green;
}

由于自定义属性没有类型,因此可能会以意想不到的方式被替换。例如,请考虑如果您使用网址定义 --my-color,会出现什么情况。

.thing {
  --my-color: url('not-a-color');
  color: var(--my-color);
}

在这里,由于未指定 --my-color,因此它不知道网址不是有效的颜色值!使用时,它会回退到默认值(color 为黑色,background 为透明)。借助 Houdini Props 和 Vals,您可以注册自定义属性,以便浏览器知道其是什么!

现在,自定义属性 --my-color 已注册为颜色!这会告知浏览器允许的值类型,以及它如何对该属性进行类型化和处理!

已注册的媒体资源详解

注册媒体资源如下所示:

window.CSS.registerProperty({
  name: '--my-color',
  syntax: '<color>',
  inherits: false,
  initialValue: 'black',
});

它支持下列选项:

name: string

自定义属性的名称。

syntax: string

如何解析自定义媒体资源。您可以在 CSS 值和单位规范中找到可能值的完整列表。默认设置为 *

inherits: boolean

它是否会继承其父级的值。默认为 true

initialValue: string

自定义属性的初始值。

深入了解 syntax。有许多有效选项,包括数字、颜色和 <custom-ident> 类型。您还可以使用以下值修改这些语法

  • 附加 + 表示它接受该语法的值以空格分隔的列表。例如,<length>+ 应为以空格分隔的长度列表
  • 附加 # 表示它接受该语法的值的逗号分隔列表。例如,<color># 是颜色的逗号分隔列表
  • 在语法或标识符之间添加 | 表示提供的任何选项均有效。例如,<color># | <url> | magic 允许使用以英文逗号分隔的颜色列表、网址或字词 magic

注意事项

Houdini 道具和值有两个注意事项。第一个问题是,一旦定义,就无法更新现有的已注册媒体资源,并且尝试重新注册媒体资源时,系统会抛出错误,指明该媒体资源已定义。

其次,与标准属性不同,系统在解析注册的属性时不会对其进行验证。而是在计算时进行验证。这意味着,在检查元素的属性时,无效值不会显示为无效;并且在有效属性后面添加无效属性也不会回退到有效属性;不过,无效属性会回退到已注册属性的默认值。

为自定义属性添加动画效果

除了类型检查之外,注册的自定义属性还提供了一个有趣的福利:能够为其添加动画效果!基本动画示例如下所示:

<script>
CSS.registerProperty({
  name: '--stop-color',
  syntax: '<color>',
  inherits: false,
  initialValue: 'blue',
});
</script>

<style>
button {
  --stop-color: red;
  transition: --stop-color 1s;
}

button:hover {
  --stop-color: green;
}
</style>

当您将鼠标悬停在该按钮上时,它会从红色变为绿色!如果未注册该属性,它将从一种颜色跳转到另一种颜色。这是因为,如果未注册,浏览器不知道一个值与下一个值之间会出现什么情况,因此无法保证能够对它们进行转换。不过,我们可以进一步改进此示例,为 CSS 渐变添加动画效果!您可以使用相同的已注册属性编写以下 CSS:

button {
  --stop-color: red;
  background: linear-gradient(var(--stop-color), black);
  transition: --stop-color 1s;
}

button:hover {
  --stop-color: green;
}

这将为 linear-gradient 中的自定义属性添加动画效果,从而为线性渐变添加动画效果。请查看下面的 Glitch,了解完整代码的运作方式,并自行试用。

总结

Houdini 即将在浏览器中推出,届时,您将能够以全新的方式使用和扩展 CSS。Paint API 已发布,现在又推出了自定义 Prop 和 Val,我们的创意工具箱不断扩大,让我们能够定义类型化的 CSS 属性,并使用这些属性来创建令人兴奋的新设计并为其添加动画效果。我们还将推出更多功能,您可以在 Houdini 问题队列中提供反馈,了解 Houdini 的后续动态。Houdini 旨在开发可说明 Web 上样式和布局“魔力”的功能,因此请大胆尝试,充分利用这些神奇的功能。

照片由 Maik Jonietz 拍摄,选自 Unsplash