CSS Houdini 实用概述
已发表: 2022-03-10新的 CSS 功能或改进需要很长时间才能从最初的草案发展到开发人员可以使用的完全支持且稳定的 CSS 功能。 基于 JavaScript 的 polyfill 可以用来替代缺乏浏览器支持的情况,以便在正式实现之前使用新的 CSS 功能。 但在大多数情况下,它们是有缺陷的。 例如,scrollsnap-polyfill 是几个可用于修复浏览器支持 CSS Scroll Snap 规范不一致的 polyfill 之一。 但即使是那个解决方案也有一些限制、错误和不一致。
使用 polyfill 的潜在缺点是它们会对性能产生负面影响并且难以正确实施。 这个缺点与浏览器的 DOM 和 CSSOM 有关。 浏览器从 HTML 标记创建DOM(文档对象模型) ,类似地,它从 CSS 标记创建CSSOM(CSS 对象模型) 。 这两个对象树相互独立。 JavaScript 在 DOM 上工作,对 CSSOM 的访问非常有限。
JavaScript Polyfill 解决方案仅在初始渲染周期完成后运行,即当 DOM 和 CSSOM 都已创建且文档已完成加载时。 在 Polyfill 对 DOM 中的样式进行更改(通过内联样式)后,它会导致渲染过程再次运行并且整个页面重新渲染。 如果它们依赖于requestAnimationFrame
方法或依赖于滚动事件等用户交互,负面的性能影响会更加明显。
Web 开发的另一个障碍是CSS 标准施加的各种限制。 例如,只有有限数量的 CSS 属性可以进行原生动画处理。 CSS 知道如何对颜色进行原生动画处理,但不知道如何对渐变进行动画处理。 尽管存在技术限制,但始终需要通过突破界限来创新和创造令人印象深刻的网络体验。 这就是为什么开发人员经常倾向于使用不太理想的解决方法或 JavaScript 来实现 CSS 目前不支持的更高级的样式和效果,例如砌体布局、高级 3D 效果、高级动画、流体排版、动画渐变、样式select
元素等
CSS 规范似乎不可能跟上行业的各种功能需求,例如对动画的更多控制、改进的文本截断、更好的input
和select
元素样式选项、更多display
选项、更多filter
选项等。
可能的解决方案是什么? 为开发人员提供一种使用各种 API 扩展 CSS 的本地方式。 在本文中,我们将看看前端开发人员如何使用 Houdini API、JavaScript 和 CSS 来做到这一点。 在每一节中,我们将分别检查每个 API,检查其浏览器支持和当前规范状态,并了解如何使用渐进式增强来实现它们。
什么是胡迪尼?
Houdini 是浏览器 API 集合的总称,旨在为 Web 开发过程和总体 CSS 标准的开发带来重大改进。 开发人员将能够使用 JavaScript 扩展 CSS 的新功能,连接到 CSS 渲染引擎,并告诉浏览器如何在渲染过程中应用 CSS。 与使用常规 polyfill 相比,这将显着提高性能和稳定性。
Houdini 规范由两个 API 组组成——高级 API和低级 API 。
高级 API与浏览器的渲染过程(样式 → 布局 → 绘制 → 合成)密切相关。 这包括:
- 绘画 API
确定视觉属性(颜色、背景、边框等)的浏览器绘制渲染步骤的扩展点。 - 布局 API
确定元素尺寸、位置和对齐方式的浏览器布局渲染步骤的扩展点。 - 动画 API
浏览器复合渲染步骤的扩展点,其中图层被绘制到屏幕上并设置动画。
低级 API构成了高级 API 的基础。 这包括:
- 类型化对象模型 API
- 自定义属性和值 API
- 字体指标 API
- 工作集
一些 Houdini API 已经可以在一些浏览器中使用,而其他 API 在它们准备好发布时也会效仿。
CSS 的未来
与迄今为止引入的常规 CSS 功能规范不同,Houdini 通过允许开发人员以更原生的方式扩展 CSS 脱颖而出。 这是否意味着 CSS 规范将停止发展,并且不会发布新的官方 CSS 功能实现? 好吧,事实并非如此。 Houdini 的目标是通过允许开发人员创建易于标准化的工作原型来帮助 CSS 功能开发过程。
此外,开发人员将能够更轻松地共享开源 CSS Worklets,并且减少对特定于浏览器的错误修复的需求。
类型化对象模型 API
在引入 Houdini 之前,JavaScript 与 CSS 交互的唯一方法是解析表示为字符串值的 CSS 并修改它们。 由于需要来回更改值类型以及在分配新值时需要手动附加值单元,手动解析和覆盖样式可能很困难且容易出错。
selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"
类型化对象模型 (Typed OM) API 通过将 CSS 值公开为类型化 JavaScript 对象,为 CSS 值添加了更多语义含义。 它显着改进了相关代码,使其更具性能、稳定性和可维护性。 CSS 值由CSSUnitValue
接口表示,该接口由一个值和一个单元属性组成。
{ value: 20, unit: "px" }
这个新接口可以与以下新属性一起使用:
-
computedStyleMap()
:用于解析计算(非内联)样式。 这是在解析或使用其他方法之前需要调用的选定元素的方法。 -
attributeStyleMap
:用于解析和修改内联样式。 这是在选定元素上可用的属性。
// Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}
请注意在设置新数值时如何使用特定的 CSS 类型。 通过使用这种语法,可以避免许多潜在的与类型相关的问题,并且生成的代码更可靠且没有错误。
get
和set
方法只是 Typed OM API 定义的所有可用方法的一小部分。 其中一些包括:
-
clear
: 移除所有内联样式 delete
:从内联样式中删除指定的 CSS 属性及其值has
:如果设置了指定的 CSS 属性,则返回布尔值append
:向支持多个值的属性添加附加值- 等等。
特征检测
var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }
W3C 规范状态
- 工作草案:发布供社区审查
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
支持的 | 支持的 | 支持的 | 不支持 | 部分支持 (*) |
*支持“实验性 Web 平台功能”或启用其他功能标志。
数据来源:Houdini 准备好了吗?
自定义属性和值 API
CSS 属性和值API 允许开发人员通过添加类型、初始值和定义继承来扩展 CSS 变量。 开发人员可以通过使用registerProperty
方法注册 CSS 自定义属性来定义 CSS 自定义属性,该方法告诉浏览器如何转换它并在出现错误时处理回退。
CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });
此方法接受输入参数,该参数是具有以下属性的对象:
-
name
:自定义属性的名称 syntax
:告诉浏览器如何解析自定义属性。 这些是预定义的值,例如<color>
、<integer>
、<number>
、<length>
、<percentage>
等。-
inherits
:告诉浏览器自定义属性是否继承其父级的值。 -
initialValue
:告诉在它被覆盖之前使用的初始值,这在发生错误时用作后备。
在以下示例中,将设置<color>
类型自定义属性。 此自定义属性将用于渐变过渡。 您可能会认为当前的 CSS 不支持背景渐变的过渡,您是对的。 注意自定义属性本身是如何在transition
中使用的,而不是用于常规background-color
转换的background
属性。
.gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }
浏览器不知道如何处理渐变过渡,但它知道如何处理颜色过渡,因为自定义属性被指定为<color>
类型。 在支持 Houdini 的浏览器上,当元素悬停时会发生渐变过渡。 渐变位置百分比也可以用 CSS 自定义属性(注册为<percentage>
类型)替换,并以与示例中相同的方式添加到过渡中。
如果registerProperty
被移除,并且在:root
选择器中注册了常规 CSS 自定义属性,则渐变过渡将不起作用。 需要使用registerProperty
以便浏览器知道它应该将其视为颜色。
在此 API 的未来实现中,可以直接在 CSS 中注册自定义属性。
@property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }
例子
这个简单的示例分别使用注册的 CSS 自定义属性为颜色和位置展示了悬停事件上的渐变颜色和位置转换。 示例存储库中提供了完整的源代码。
特征检测
if (CSS.registerProperty) { /* ... */ }
W3C 规范状态
- 工作草案:发布供社区审查
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
支持的 | 支持的 | 支持的 | 不支持 | 不支持 |
数据来源:Houdini 准备好了吗?
字体指标 API
Font Metrics API 仍处于非常早期的开发阶段,因此其规范可能会在未来发生变化。 在其当前草案中, Font Metrics API将提供测量屏幕上呈现的文本元素尺寸的方法,以便开发人员能够影响文本元素在屏幕上的呈现方式。 这些值很难或不可能用当前的特性来衡量,因此这个 API 将允许开发人员更轻松地创建与文本和字体相关的 CSS 特性。 多行动态文本截断是这些功能之一的示例。
W3C 规范状态
- 创意合集:暂未提交规范草案
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
不支持 | 不支持 | 不支持 | 不支持 | 不支持 |
数据来源:Houdini 准备好了吗?
工作集
在转向其他 API 之前,解释一下 Worklets 概念很重要。 Worklet是在渲染期间运行的脚本,独立于主要的 JavaScript 环境。 它们是渲染引擎的扩展点。 它们专为并行性(具有 2 个或更多实例)和线程无关而设计,减少了对全局范围的访问,并在需要时由渲染引擎调用。 Worklet 只能在 HTTPS(在生产环境中)或 localhost(用于开发目的)上运行。
Houdini 引入了以下 Worklets 来扩展浏览器渲染引擎:
- 绘制工作集 - 绘制 API
- 动画工作集 - 动画 API
- 布局工作集 - 布局 API
绘画 API
Paint API 允许开发人员使用 JavaScript 函数直接绘制元素的背景、边框或使用 2D 渲染上下文的内容,这是 HTML5 Canvas API 的子集。 Paint API 使用 Paint Worklet 来绘制动态响应 CSS 变化的图像(例如 CSS 变量的变化)。 任何熟悉 Canvas API 的人都会对 Houdini 的 Paint API 感到宾至如归。
定义 Paint Worklet 需要几个步骤:
- 使用
registerPaint
函数编写和注册一个 Paint Worklet - 使用
CSS.paintWorklet.addModule
函数在 HTML 文件或主 JavaScript 文件中调用 Worklet - 在 CSS 中使用带有 Worklet 名称和可选输入参数的
paint()
函数。
让我们看一下用于注册 Paint Worklet 并定义其功能的registerPaint
函数。
registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });
registerPaint
函数由几个部分组成:
-
inputProperties
:
Worklet 将跟踪的一组 CSS 自定义属性。 该数组表示绘制工作集的依赖关系。 -
inputArguments
:
可以从 CSS 内部的paint
函数传递的输入参数数组。 -
contextOptions
:允许或禁止颜色的不透明度。 如果设置为false
,所有颜色都将以完全不透明度显示。 -
paint
:提供以下参数的主函数:-
ctx
: 2D 绘图上下文,几乎与 Canvas API 的 2D 绘图上下文相同。 -
size
:包含元素宽度和高度的对象。 值由布局呈现过程确定。 画布大小与元素的实际大小相同。 -
properties
:inputProperties
中定义的输入变量 args
:在 CSS 中的paint
函数中传递的输入参数数组
-
注册 Worklet 后,只需提供文件路径即可在 HTML 文件中调用它。
CSS.paintWorklet.addModule("path/to/worklet/file.js");
任何 Worklet 也可以从外部 URL(例如,从内容交付网络)添加,这使得它们成为模块化和可重用的。
CSS.paintWorklet.addModule("https://url/to/worklet/file.js");
调用 Worklet 后,可以使用paint
函数在 CSS 中使用它。 此函数接受 Worklet 的注册名称作为第一个输入参数,其后的每个输入参数都是一个自定义参数,可以传递给 Worklet(在 Worklet 的inputArguments
中定义)。 从那时起,浏览器确定何时调用 Worklet 以及响应哪些用户操作和 CSS 自定义属性值更改。
.exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }
例子
以下示例展示了 Paint API 和一般 Worklet 的可重用性和模块化。 它直接使用 Google Chrome Labs 存储库中的涟漪 Worklet,并在具有不同样式的不同元素上运行。 示例存储库中提供了完整的源代码。
特征检测
if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }
W3C 规范状态
- 候选推荐:稳定的工作草案准备实施
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
支持的 | 支持的 | 支持的 | 不支持 | 不支持 |
数据来源:Houdini 准备好了吗?
动画 API
Animation API 扩展了 Web 动画,提供了监听各种事件(滚动、悬停、单击等)的选项,并通过使用 Animation Worklet 在其自己的专用线程上运行动画来提高性能。 它允许用户操作来控制以高性能、非阻塞方式运行的动画流。
与任何 Worklet 一样,Animation Worklet 需要先注册。
registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });
这个类包含两个函数:
-
constructor
:在创建新实例时调用。 用于一般设置。 -
animate
:包含动画逻辑的主函数。 提供以下输入参数:-
currentTime
: 定义时间线中的当前时间值 effect
: 此动画使用的一系列效果
-
注册 Animation Worklet 后,需要将其包含在主 JavaScript 文件中,需要定义动画(元素、关键帧、选项)并使用选定的时间线实例化动画。 时间轴概念和网络动画基础知识将在下一节中解释。
/* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */
时间线映射
Web 动画基于时间线和当前时间到效果本地时间的时间线的映射。 例如,让我们看一个具有 3 个关键帧(开始、中间、最后一个)的重复线性动画,该动画在页面加载(延迟)后 1 秒运行,持续时间为 4 秒。
示例中的效果时间线如下所示(持续时间为 4 秒,无延迟):
效果时间线(4秒持续时间) | 关键帧 |
---|---|
0ms | 第一个关键帧 - 动画开始 |
2000毫秒 | 中间关键帧 - 动画正在进行中 |
4000毫秒 | 最后一个关键帧 - 动画结束或重置到第一个关键帧 |
为了更好地理解effect.localTime
,通过将其值设置为 3000 毫秒(考虑到 1000 毫秒延迟),生成的动画将被锁定到效果时间轴中的中间关键帧(1000 毫秒延迟 + 中间关键帧 2000 毫秒)。 将值设置为 7000 毫秒和 11000 毫秒会产生相同的效果,因为动画以 4000 毫秒的间隔(动画持续时间)重复。
animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }
当具有恒定的effect.localTime
值时不会发生动画,因为动画被锁定在特定的关键帧中。 为了正确地为元素设置动画,它的effect.localTime
需要是动态的。 该值必须是一个取决于currentTime
输入参数或其他变量的函数。
以下代码显示了时间线的 1:1(线性函数)映射以影响本地时间的功能表示。
animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
时间线 ( document.timeline ) | 映射效果当地时间 | 关键帧 |
---|---|---|
startTime + 0ms(经过的时间) | startTime + 0 毫秒 | 第一的 |
startTime 时间 + 1000 毫秒(经过的时间) | startTime 时间 + 1000 毫秒(延迟) + 0 毫秒 | 第一的 |
startTime + 3000ms(经过的时间) | startTime 时间 + 1000 毫秒(延迟) + 2000 毫秒 | 中间 |
startTime 时间 + 5000 毫秒(经过的时间) | startTime 时间 + 1000 毫秒(延迟) + 4000 毫秒 | 最后/第一个 |
startTime + 7000ms(经过的时间) | startTime 时间 + 1000 毫秒(延迟) + 6000 毫秒 | 中间 |
startTime + 9000ms(经过的时间) | startTime 时间 + 1000 毫秒(延迟) + 8000 毫秒 | 最后/第一个 |
时间线不限于与效果本地时间的 1:1 映射。 Animation API 允许开发人员通过使用标准 JavaScript 函数来操作animate
函数中的时间轴映射来创建复杂的时间轴。 动画也不必在每次迭代中表现相同(如果重复动画)。
动画不必依赖于文档的时间线,它只从加载的那一刻开始计算毫秒数。 通过使用ScrollTimeline
对象,可以将滚动事件等用户操作用作动画的时间线。 例如,动画可以在用户滚动到 200 像素时开始,并且可以在用户在屏幕上滚动到 800 像素时结束。
const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...
动画将自动适应用户滚动速度并保持流畅和响应。 由于 Animation Worklet 运行在主线程之外并连接到浏览器的渲染引擎,因此依赖于用户滚动的动画可以流畅地运行并且非常高效。
例子
以下示例展示了如何实现非线性时间线。 它使用修改后的高斯函数,并在同一时间轴上应用平移和旋转动画。 示例存储库中提供了完整的源代码。
特征检测
if (CSS.animationWorklet) { /* ... */ }
W3C 规范状态
- 第一个公共工作草案:准备好进行社区审查,容易发生规范变更
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
部分支持 (*) | 部分支持 (*) | 部分支持 (*) | 不支持 | 不支持 |
*支持启用“Experimental Web Platform features”标志。
数据来源:Houdini 准备好了吗?
布局 API
Layout API 允许开发人员通过定义可用于display
CSS 属性的新布局模式来扩展浏览器的布局呈现过程。 布局 API 引入了新概念,非常复杂,并为开发自定义布局算法提供了很多选项。
与其他 Worklet 类似,布局 Worklet 需要先注册和定义。
registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });
Worklet register 包含以下方法:
-
inputProperties
:
Worklet 将跟踪的一组 CSS 自定义属性属于父布局元素,即调用此布局的元素。 该数组表示布局工作集的依赖关系。 -
childrenInputProperties
:
Worklet 将跟踪的一组 CSS 自定义属性属于父布局元素的子元素,即设置此布局的元素的子元素。 -
layoutOptions
:定义以下布局属性:-
childDisplay
:可以有一个预定义的值block
或normal
。 确定框是显示为块还是内联。 -
sizing
:可以具有block-like
或manual
的预定义值。 它分别告诉浏览器预先计算大小或不预先计算(除非明确设置大小)。
-
-
intrinsicSizes
:定义框或其内容如何适应布局上下文。-
children
:父布局元素的子元素,即调用此布局的元素的子元素。 -
edges
:盒子的布局边缘 styleMap
: 框的类型化 OM 样式
-
layout
:执行布局的主要功能。-
children
:父布局元素的子元素,即调用此布局的元素的子元素。 -
edges
:盒子的布局边缘 constraints
:父布局的约束styleMap
: 框的类型化 OM 样式breakToken
:用于在分页或打印时恢复布局的中断令牌。
-
与 Paint API 的情况一样,浏览器渲染引擎决定何时调用paint Worklet。 它只需要添加到 HTML 或主 JavaScript 文件中。
CSS.layoutWorklet.addModule('path/to/worklet/file.js');
最后,它需要在 CSS 文件中引用
.exampleElement { display: layout(exampleLayout); }
Layout API 如何执行布局
在前面的示例中, exampleLayout
是使用 Layout API 定义的。
.exampleElement { display: layout(exampleLayout); }
这个元素称为父布局,它包含在由内边距、边框和滚动条组成的布局边缘中。 Parent Layout 由称为Current Layouts的子元素组成。 当前布局是可以使用布局 API 自定义布局的实际目标元素。 例如,当使用display: flex;
在一个元素上,它的子元素被重新定位以形成 flex 布局。 这类似于使用 Layout API 所做的事情。
每个Current Layout都包含Child Layout ,它是 LayoutChild(元素、 ::before
和::after
伪元素)的布局算法,而LayoutChild是一个 CSS 生成的框,仅包含样式数据(无布局数据)。 LayoutChild 元素由浏览器渲染引擎在样式步骤中自动创建。 Layout Child 可以生成一个Fragment来实际执行布局渲染动作。
例子
与 Paint API 示例类似,此示例直接从 Google Chrome 实验室存储库导入砌体布局 Worklet,但在此示例中,它用于图像内容而不是文本。 示例存储库中提供了完整的源代码。
特征检测
if (CSS.layoutWorklet) { /* ... */ }
W3C 规范状态
- 第一个公共工作草案:准备好进行社区审查,容易发生规范变更
浏览器支持
谷歌浏览器 | 微软边缘 | 歌剧浏览器 | 火狐 | 苹果浏览器 |
---|---|---|---|---|
部分支持 (*) | 部分支持 (*) | 部分支持 (*) | 不支持 | 不支持 |
*支持启用“Experimental Web Platform features”标志。
数据来源:Houdini 准备好了吗?
Houdini 和渐进增强
尽管 CSS Houdini 还没有最佳的浏览器支持,但它现在可以在考虑渐进增强的情况下使用。 如果您不熟悉渐进式增强,那么值得查看这篇解释得很好的方便文章。 如果您今天决定在您的项目中实施 Houdini,请记住以下几点:
- 使用特征检测来防止错误。
每个 Houdini API 和 Worklet 都提供了一种简单的方法来检查它是否在浏览器中可用。 使用功能检测将 Houdini 增强仅应用于支持它并避免错误的浏览器。 - 仅用于演示和视觉增强。
在尚不支持 Houdini 的浏览器上浏览网站的用户应该可以访问网站的内容和核心功能。 用户体验和内容呈现不应该依赖于 Houdini 功能,应该有一个可靠的后备。 - 使用标准的 CSS 后备。
例如,常规 CSS 自定义属性可用作使用自定义属性和值 API 定义的样式的后备。
首先专注于开发高性能和可靠的网站用户体验,然后将 Houdini 功能用于装饰目的作为渐进式增强。
结论
Houdini API 最终将使开发人员能够使用于样式操作和装饰的 JavaScript 代码更接近浏览器的渲染管道,从而获得更好的性能和稳定性。 通过允许开发人员连接到浏览器渲染过程,他们将能够开发各种 CSS polyfill,这些 polyfill 可以很容易地共享、实现,并有可能添加到 CSS 规范本身中。 Houdini 还将使开发人员和设计人员在处理样式、布局和动画时减少受 CSS 限制的限制,从而带来令人愉悦的新 Web 体验。
现在可以将 CSS Houdini 功能添加到项目中,但要严格考虑渐进增强。 这将使不支持 Houdini 功能的浏览器能够无错误地呈现网站并提供最佳用户体验。
随着 Houdini 获得牵引力和更好的浏览器支持,开发者社区将提出什么将是令人兴奋的。 以下是来自社区的一些很棒的 Houdini API 实验示例:
- CSS Houdini 实验
- CSS Houdini 交互式介绍
- Google Chrome 实验室的 Houdini 示例
参考
- W3C Houdini 规范草案
- Houdini 状态(Chrome 开发者峰会 2018)
- Houdini 的动画工作集 - Google Developers
- CSS Houdini 交互式介绍