Houdini,CSS 别样助攻,让你的界面效果更酷炫
【摘要】 认识 Houdini:源自一场"邂逅"吃饭看书刷视频,修身养性三件套。遇到论坛就想逛一逛,遇到知识点就想用一用。这不,这天我正闲心,所以所以刷了刷 MDN 的网站。点到Web 开发者指南这页下,看到了一个有点陌生的词汇——CSS Houdini。我顺着自己的"脑机接口",翻了翻脑袋里的前端知识库,没什么印象。没印象没关系,可以现学。了解 Houdini:全方位扫描中Houdini 是一组底层...
认识 Houdini:源自一场"邂逅"
吃饭看书刷视频,修身养性三件套。遇到论坛就想逛一逛,遇到知识点就想用一用。
这不,这天我正闲心,所以所以刷了刷 MDN 的网站。点到Web 开发者指南这页下,看到了一个有点陌生的词汇——CSS Houdini。
我顺着自己的"脑机接口",翻了翻脑袋里的前端知识库,没什么印象。
没印象没关系,可以现学。
了解 Houdini:全方位扫描中
Houdini 是一组底层 API,它们公开了 CSS 引擎的各个部分,从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展 CSS。它们使开发人员可以直接访问CSS 对象模型 (CSSOM),使开发人员可以编写浏览器可以解析为 CSS 的代码,从而创建新的 CSS 功能,而无需等待它们在浏览器中本地实现。
"一组"、"它们",根据这些关键词不难看出,Houdini 并非 CSS 的某个特定的属性,想要熟悉 Houdini,并确定实际可应用的业务场景,也要采用不同的学习策略:
先来总结这组 API 的共性,再逐个认识每一个的特点,根据各自的特别,联想到不同的展示效果。
Houdini 的特点
我从 MDN 对 Houdini 的大段大段的介绍文档中,提炼了一下 Houdini 的特点:
- 使用 Houdini,当样式改变时,浏览器可以解析的更快;
- 可以使用 JavaScript 动态修改 CSS 样式;
- 可以通过 Worklet 创建模块式的 CSS,也能够访问元素的自定义属性,而非作为函数参数传递。
这么看,Houdini 对 CSS 的操作确实够强。
Houdini 的 APIs
以下为 MDN 中罗列的 APIs:

我也搜了一下 W3C,发现有些出入,感兴趣的可做详细了解。
Houdini VS CSS-in-JS
除了 Houdini 提供的 APIs 的用途,我还关心的一点是,Houdini 与 CSS-in-JS 的差异。换句话说,我挺关心,实际业务场景中具体应该采用哪种方式来操作 CSS。
CSS-in-JS 是一种将 CSS 维护在 JavaScript 中的技术方案。从被提出到现在,CSS-in-JS 已经拥有了众多方案。
两者都支持在 JavaScript 修改 CSS,但是方式不同:
- Houdini 提供的 Typed OM API 可以在 JavaScript 中直接访问类型化JavaScript对象的 CSS 的值,进行读取和写入;
- CSS-in-JS 的方案中,是在 JavaScript 文件中定义一系列的CSS属性,然后被引入到页面,解析之后,会把对应的 CSS 样式通过 style 标签的形式插入到该页面的 Head 中。
如何选择开发方案,可以借鉴MDN 备注中的这段话:
在 Houdini 的帮助下你能够在 css 中实现你自己的布局、栅格、或者区域特性,但是这么做并不是最佳实践。CSS 工作组已经做了许多努力来确保 CSS 中的每一项特性都能正常运行,覆盖各种边界情况,同时考虑到了安全、隐私,以及可用性方面的表现。
熟悉 Houdini:代码一上手,就知有没有
代码实验开始前,先讲一个我遇到的阻塞性的问题—— Chrome 浏览器跨域。
在使用"CSS.paintWorklet.addModule"引入本地 JS 文件之后,Chrome 浏览器出现了跨域报错。
因为是 Mac 本,所以我采用的解决方案是:
使用命令打开一个支持设置"--disable-web-security"的浏览器页,命令如下:
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/你电脑的名称/Documents/MyChromeDevUserData
实例1:简历模版同款背景装饰
UI 展示效果
我记得之前下载的简历模版中,有一款的标题装饰像梳子的齿,大致展示效果如下图:
Painting API 搞定绘制
上面思维导图中有 Painting API 的介绍:
该 API 允许开发者通过 paint() 方法书写 JavaScript 函数,以控制绘制元素的背景、边框或者内容区域。
使用 Painting API 可以创建复杂、有趣的图像。
注:该展示效果在 MDN 上有同款。
paint()
介绍 |
它是一个CSS函数,用于定义了使用PaintWorklet生成的<image>值。 |
语法 |
paint(workletName, ...parameters) |
属性 |
workletName:注册的worklet的名称 parameters:要传递到paintWorklet的可选附加参数 |
paint worklet
registerPaint(
'headerHighlight',
class {
static get inputProperties() {
return ['--highColor'];
}
static get contextOptions() {
return { alpha: true };
}
paint(ctx, size, props) {
/* set where to start the highlight & dimensions */
const x = 0;
const y = size.height * 0.3;
const blockWidth = size.width * 0.33;
const highlightHeight = size.height * 0.85;
const color = props.get('--highColor');
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(blockWidth, y);
ctx.lineTo(blockWidth + highlightHeight, highlightHeight);
ctx.lineTo(x, highlightHeight);
ctx.lineTo(x, y);
ctx.closePath();
ctx.fill();
/* create the dashes */
for (let start = 0; start < 8; start += 2) {
ctx.beginPath();
ctx.moveTo(blockWidth + start * 10 + 10, y);
ctx.lineTo(blockWidth + start * 10 + 20, y);
ctx.lineTo(blockWidth + start * 10 + 20 + highlightHeight, highlightHeight);
ctx.lineTo(blockWidth + start * 10 + 10 + highlightHeight, highlightHeight);
ctx.lineTo(blockWidth + start * 10 + 10, y);
ctx.closePath();
ctx.fill();
}
} // paint
},
);
HTML
<h2 class="fancy">教育背景</h2>
<h2 class="fancy">工作经历</h2>
<h2 class="fancy">自我评价</h2>
设置CSS
.fancy {
background-image: paint(headerHighlight);
--highColor: hsl(155 90% 60% / 0.7);
}
.fancy:nth-child(2) {
--highColor: hsl(255 90% 60% / 0.5);
}
.fancy:nth-child(3) {
--highColor: hsl(355 90% 60% / 0.3);
}
注册worklet
<script>
CSS.paintWorklet.addModule('header-highlight.js');
</script>
实例2:渐变的渐变背景
UI 展示效果
properties and values API 搞定绘制
HTML
<button class="registered">Background Registered</button>
<button class="unregistered">Background Not Registered</button>
CSS
.registered {
--registered: #c0ffee;
background-image: linear-gradient(to right, #fff, var(--registered));
transition: --registered 1s ease-in-out;
}
.registered:hover,
.registered:focus {
--registered: #b4d455;
}
.unregistered {
--unregistered: #c0ffee;
background-image: linear-gradient(to right, #fff, var(--unregistered));
transition: --unregistered 1s ease-in-out;
}
.unregistered:hover,
.unregistered:focus {
--unregistered: #b4d455;
}
button {
height: 40px;
display: block;
width: 300px;
font-size: 16px;
margin-bottom: 10px;
}
JavaScript
<script>
if (CSS.registerProperty) {
CSS.registerProperty({
name: '--registered',
syntax: '<color>',
inherits: false,
initialValue: 'red',
});
}
</script>
小结
1、使用 Painting API 绘制图形,最后有些 Canvas 的基础。实现时,会用到 Canvas 的 API。
2、有些过渡效果无法直接实现,比如背景渐变动画,这个时候自定义属性就派上用场了。properties and values API 便支持自定义 CSS 属性。
总结
对于开发者而言,活学活用是本能。所以遇见 CSS Houdini,了解它、熟悉它、运用它,也就自然而然,顺势而为。
看完只觉 Houdini 的甚是强大,使用它,界面效果愈发炫酷,且可以帮助实现一些特定的效果。
但是,想要 Houdini 用的顺,也有有学习成本,再加上最佳实践的考虑。笔者建议对它深入了解、多做些效果实验之后再做选择。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)