本文首发于 掘金,未经许可严禁转载前言 最近研究了下 Houdini,它是 CSS 领域的一个重大变革,它的终极目标是实现 CSS 属性的完全兼容,其中最受关注的特性之一就是它能正确地 polyfill CSS!这么说比较抽象,它到底是做什么的呢,如何使用呢,本文来讲解一二。
基本概念 Houdini 是一组底层 api,它公开了 CSS 引擎的部分内容,使开发人员能够通过
hook
到浏览器渲染引擎的样式和布局过程来扩展 CSS。它可以让开发者直接访问 CSS 对象模型(CSSOM) ,使开发者能够编写浏览器可以解析为 CSS 的代码,从而创建新的 CSS 特性,而无需等待这些特性在浏览器中自行实现。此外,它还能用于创造一些自定义的,带有类型检查和默认值的 CSS 属性。
Houdini API 介绍 一、CSS property 和值 API CSS 其实已经有自定义属性了,这能解锁太多新玩法。而 CSS Properties and Values API 的出现进一步推动自定义属性,还允许自定义属性添加不同的类型,允许属性类型检查、设置默认值以及定义属性是否可以继承值,大大增加自定义属性能力。
这个 API 最大卖点是开发者可以在自定义属性上做动画,这是仅凭借现在技术是做不到的。
先来看一个案例,CSS 变量可能很多人都有使用过,它之所以神奇,是因为它是动态的。但它的弱点之一是无法转换,如果你尝试为变量设置动画,它只会从一个属性翻转到另一个属性,之间没有过渡效果。
文章图片
文章图片
Codepen Demo
这是因为 CSS 变了没有任何意义,它没有任何类型,因此浏览器不知道特定变量是否是颜色、百分比、数字等。
CSS Houdini 提供了为变量分配类型的能力。如果你为变量分配了错误类型的值,浏览器将忽略它并选择默认值。
CSS.registerProperty({
name: '--start',
syntax: '',
inherits: true,
initialValue: 'purple'
})
CSS Houdini's Properties 和 Values API 允许我们为 CSS 变量指定类型。使用强类型的 CSS 变量,它最终可以被转换。最流行的用例之一是动画渐变。
文章图片
文章图片
Codepen Demo
使用方式有2种
1、CSS 中定义 CSS 属性
@property
@property --my-color {
syntax: '';
inherits: false;
initial-value: #c0ffee;
}// 使用:
div {
color: var(--my-color);
}
@property --property-name
中的 --property-name
就是自定义属性的名称,定义后可在 CSS 中通过 var(--property-name)
进行引用- syntax:该自定义属性的语法规则,也可以理解为表示定义的自定义属性的类型
- inherits:是否允许继承
- initial-value:初始值
CSS.registerProperty
window.CSS.registerProperty({
name: '--my-color',
syntax: '',
inherits: false,
initialValue: '#c0ffee',
})// css中使用
div {
color: var(--my-color);
}
二、CSS Paint API(Worklets) 该 API 使我们能够通过
Canvas
以编程方式为需要图像的任何 CSS 属性创建图像。此类属性的示例是 background-image
和 border-image
。CSS Paint API 可以简单理解为把
Canvas
作为普通元素的背景图,也就是说 CSS 的 background-image
就是一个 Canvas
,可以利用这个特性为很多元素绘制背景特效。小示例
下面我们为
textarea
写一个棋盘背景,效果如下:【CSS Houdini: Properties, Values, and the Paint API】
文章图片
textarea {
background-image: paint(checkerboard);
}
// checkerboard.js
class CheckerboardPainter {
paint(ctx, geom, properties) {
// Use `ctx` as if it was a normal canvas
const colors = ['red', 'green', 'blue'];
const size = 32;
for(let y = 0;
y < geom.height/size;
y++) {
for(let x = 0;
x < geom.width/size;
x++) {
const color = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.fillStyle = color;
ctx.rect(x * size, y * size, size, size);
ctx.fill();
}
}
}
}// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);
Codepen Demo
它的固定用法套路分三步走:
- CSS 中 paint(abc);
- JS 添加模块 CSS.paintWorklet.addModule('xxx.js');
- xxx.js 中代码套路固定,在下面注释位置写绘制代码即可;
registerPaint('abc', class { paint(context, size, properties, args) { // 绘制代码在这里.... } });
registerPaint 方法注册了一个 Paint 类 abc 以供调用,这个类的核心在于它的paint
方法。paint
方法用于描述自定义的绘制逻辑,它接收四个参数:
- context:绘图的上下文,API 全部都是来自 Canvas 的
CanvasRenderingContext2D
,不过为了安全限制,有些 Canvas 中的 API 是不能使用的。 - size:节点的尺寸信息,同时也是 canvas 可绘制范围(画板)的尺寸信息。
- properties:包含节点的 CSS 属性,需要调用静态方法 inputProperties 声明注入。
- args:CSS 中调用 Paint 类时传入的参数,需要调用静态方法 inputArguments 声明注入。
const el = document.getElementById('el');
el.style.opacity = 0.3;
这会存在一个问题
el.style.opacity
的类型并非一个数字,而是一个字符串。如果要像将其进行数学计算,那就需要先进行类型转换,所以这就是 Typed OM 要解决的问题。将 CSSOM 值字符串转换为有意义的类型化 JavaScript 表示并返回可能会导致显着的性能开销。该规范将 CSS 值公开为类型化的 JavaScript 对象,以使操作它们更容易且性能更高。
它的卖点有:
- 更好的性能,由于减少了字符串操作,对于 CSSOM 的操作性能得到了更进一步的提升,由 Tab Akins(github 用户)提供的测试表明,操作 Typed OM 比直接操作 CSSOM 字符串带来了大约 30% 的速度提升;
- 错误处理,对于错误的 CSS 值,将会抛出错误;
- 在数值对象上调用简单的算术运算方法,绝对单位之间还能方便得尽兴单位转换;
在 Typed OM 中,数值和数值的单位是分开的,所获取的是一个
CSSUnitValue
对象,内置数值 value
和单位 unit
两个键。// 要对一个元素的样式赋值,除了可以使用 CSS.px 构建之外,还能接受字符串
el.attributeStyleMap.set('height', CSS.px(10));
el.attributeStyleMap.set('height', '10px');
// 对于获取,返回 CSSUnitValue 对象,访问其 value 属性即可得到数字类型的值
el.attributeStyleMap.get('height').value;
// 10
el.attributeStyleMap.get('height').unit;
// 'px'
其它用法自性探索。
小结
Typed OM 对于其它 Houdini API 的意义:Typed OM 的使用在为往后更高效地发展各个 Houdini 标准打下了基础,包括自定义属性,布局以及绘制相关标准。
CSS Typed OM 解决了开发时修改数值的问题,同时通过减少字符串操作增加了总体的操作性能,使得我们在操作 CSSOM 不仅方便还高效,配合
requestAnimationFrame
还能制作出性能更优的自定义动画。四、CSS Layout API CSS Layout API 的招牌就是让开发者自定义布局方式,比如瀑布流等。让 Web 布局有更多的想象空间,由于浏览器还没有完全开放给开发者,并且学习成本较高,需要CSS和JS同时具有一定造诣才能驾驭,因此本文不做展开。
Reference
- https://drafts.css-houdini.or...
- https://zhuanlan.zhihu.com/p/...
- https://aysha.me/2019/08/css-...
- https://www.zhangxinxu.com/wo...
推荐阅读
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- JavaScript|JavaScript之DOM增删改查(重点)
- 网络|一文彻底搞懂前端监控
- css|我用css精灵图拼接了自己的英文名字,不会还有人不知道精灵图技术吧()
- css|css三角的做法及其案例
- css|css中元素的显示与隐藏
- JavaWeb|JavaWeb学习——CSS
- flex|C语言-使用goto语句从循环中跳出
- java|你跳一次涨多少(今天见识到跳槽天花板!!)