滚动驱动的动画

W3C 工作草案,

关于本文件的更多详情
此版本:
https://www.w3.org/TR/2023/WD-scroll-animations-1-20230606/
最新发布版本:
https://www.w3.org/TR/scroll-animations-1/
编辑草案:
https://drafts.csswg.org/scroll-animations-1/
历史:
https://www.w3.org/standards/history/scroll-animations-1
反馈:
CSSWG 问题库
规范内联
编辑:
(特邀专家)
(Mozilla)
(Apple)
(Microsoft)
Elika J. Etemad / fantasai (特邀专家)
Robert Flack (Google)
前编辑:
(Google)
Mantaroh Yoshinaga
(Google)
建议编辑此规范:
GitHub 编辑器

摘要

定义了一个API和标记,用于创建与滚动容器的滚动偏移相关的动画。

CSS 是一种语言,用于描述结构化文档(如HTML和XML)在屏幕、纸张等上的渲染效果。

本文档的状态

本节描述了本文件在发布时的状态。 当前W3C出版物的列表 和此技术报告的最新修订版本 可在 W3C技术报告索引 中找到。

本文件由 CSS 工作组 作为 工作草案 发布 ,遵循 推荐轨道。 作为工作草案发布 并不意味着 W3C 及其成员的认可。

这是一个草案文档 可能会被更新、替换 或被其他文档取代。 将此文档作为其他进展工作进行引用是不合适的。

请通过 在 GitHub 上提交问题 (首选)发送反馈, 标题中包含规范代码 “scroll-animations”,例如: “[scroll-animations] …评论摘要…”。 所有问题和评论均已 存档。 另外,反馈可以发送到公共邮件列表 (存档) www-style@w3.org

此文件受 2021年11月2日W3C流程文档 管辖。

本文件由一个在 W3C 专利政策 下运行的小组制作。 W3C 维护了一个 公开的专利披露列表, 该页面还包括披露专利的说明。 个人如果知道与该小组交付物相关的专利 必须根据 W3C 专利政策第6节 披露相关信息。

1. 介绍

本规范定义了基于滚动容器的滚动进度来驱动动画进度的机制。 这些 滚动驱动的动画 使用基于滚动位置的时间线, 而不是基于时钟时间的时间线。 此模块提供了基于 Web Animations API 的命令式 API 和基于 CSS Animations 的声明式 API。[WEB-ANIMATIONS-1]

有两种类型的 滚动驱动的时间线

注意:滚动驱动的动画,其进度与滚动位置相关, 不同于滚动触发的动画,后者由滚动位置触发,但其进度由时间驱动。

1.1. 与其他规范的关系

Web Animations [WEB-ANIMATIONS-1] 定义了 Web 平台上动画的抽象概念模型, 该模型的元素包括 动画 及其 时间线, 以及相关的编程接口。 本规范通过定义 滚动驱动的时间线 并允许其驱动 动画 的进度,扩展了 Web Animations 模型, 从而创建 滚动驱动的动画

本规范介绍了与这些概念交互的编程接口, 以及将这些概念应用于 CSS 动画的 CSS 属性 [CSS-ANIMATIONS-1]。 在这些 CSS 属性的行为以编程接口为基础描述的情况下,用户代理 即使不支持脚本, 也可以通过实现 CSS 功能来符合本规范, 使其行为如同底层编程接口存在一样。

与 CSS 中大多数操作一样,除了 选择器 匹配外, 本规范中的功能作用于 扁平化的元素树

1.2. 与异步滚动的关系

某些用户代理支持与布局或脚本异步的滚动。 本规范旨在与这种架构兼容。

特别是,本规范允许以不需要每次采样效果时运行脚本的方式表达滚动驱动的效果。 支持异步滚动的用户代理可以(但不要求)异步采样此类效果。

1.3. 值定义

本规范遵循 CSS 属性定义约定,使用 值定义语法 [CSS-VALUES-3]。 未在本规范中定义的值类型 在 CSS 值与单位模块 [CSS-VALUES-3] 中定义。 与其他 CSS 模块的结合可能会扩展这些值类型的定义。

除了各自定义中的特定属性值外, 本规范定义的所有属性 还接受 CSS 宽泛关键词 作为其属性值。 为了可读性,这些关键词没有被明确重复。

2. 滚动进度时间线

滚动进度时间线 是与 滚动容器 在特定轴上滚动位置的进度相关联的时间线。 最开始的滚动位置代表 0% 进度, 而最末尾的滚动位置代表 100% 进度。

滚动进度时间线 可以通过 animation-timeline 中的 scroll() 函数表示法 匿名引用,或通过名称引用(参见 § 4.2 命名时间线范围和查找) 在使用 scroll-timeline 属性声明它们之后。 在 Web Animations API 中, 它们可以通过 ScrollTimeline 对象匿名表示。

2.1. 计算滚动进度时间线的进度

当前时间 的进度是通过以下公式计算的:滚动偏移量 ÷ (可滚动溢出 尺寸滚动容器 尺寸)

如果 0% 位置和 100% 位置重合 (即 当前时间 公式中的分母为零), 时间线将变为 非活动状态

分页媒体 中, 原本引用文档视口的 滚动进度时间线 也将处于 非活动状态

2.2. 匿名滚动进度时间线

2.2.1. scroll() 表示法

scroll() 函数表示法 可以作为 <single-animation-timeline> 值用于 animation-timeline,并指定 滚动进度时间线。 其语法为:

<scroll()> = scroll( [ <scroller> || <axis> ]? )
<axis> = block | inline | x | y
<scroller> = root | nearest | self

默认情况下,scroll() 引用最近的祖先 块轴滚动容器。 其参数修改如下查找方式:

块轴
指定使用 块轴 的进度测量 滚动容器。 (默认。)
行轴
指定使用 行轴 的进度测量 滚动容器
x
指定使用 水平轴 的进度测量 滚动容器
y
指定使用 垂直轴 的进度测量 滚动容器
最近的
指定使用最近的祖先 滚动容器。 (默认。)
指定使用文档视口作为 滚动容器
自身
指定使用元素自身的 主盒 作为 滚动容器。 如果 主盒 不是 滚动容器, 那么 滚动进度时间线非活动状态

注意:进度是参考 滚动原点, 它可以根据 书写模式 进行翻转, 即使指定了 xy

根元素 的引用将传播到文档视口 (其功能相当于 滚动容器)。

每次使用 scroll() 都对应于 Web Animations API 中的 ScrollTimeline 实例, 即使多个元素使用 scroll() 引用相同的 滚动容器 并带有相同的参数。

2.2.2. ScrollTimeline 接口

enum ScrollAxis {
  "block",
  "inline",
  "x",
  "y"
};

dictionary ScrollTimelineOptions {
  Element? source;
  ScrollAxis axis = "block";
};

[Exposed=Window]
interface ScrollTimeline : AnimationTimeline {
  constructor(optional ScrollTimelineOptions options = {});
  readonly attribute Element? source;
  readonly attribute ScrollAxis axis;
};

ScrollTimeline 是一个 AnimationTimeline, 它代表一个 滚动进度时间线。 它可以传递给 Animation 构造函数或 animate() 方法, 以将动画与 滚动进度时间线 关联起来。

source, 类型为 Element,只读,可为空

驱动时间线进度的 滚动容器 元素的滚动位置。

axis, 类型为 ScrollAxis,只读

驱动时间线进度的滚动轴。 参见上方 <axis> 的值定义。

继承的属性:

currentTime (继承自 AnimationTimeline

表示 滚动容器 的滚动进度, 以百分比 CSSUnitValue 表示, 其中 0% 表示其最初的滚动位置 (在 书写模式 下的 滚动容器)。 当时间线处于 非活动状态 时为 null。

虽然 0% 通常表示 滚动容器 的初始滚动位置, 但这可能会根据其 内容分布 而有所不同。 参见 CSS 盒子对齐 3 § 5.3 溢出和滚动位置。 这符合我们的需求吗?

添加一条注释,说明 currentTime 是否可以为负数或大于 100%。

ScrollTimeline(options)

使用以下步骤创建一个新的 ScrollTimeline 对象:

  1. timeline 设为新的 ScrollTimeline 对象。

  2. source 设置为 timeline 的:

    如果 optionssource 成员存在且不为空,

    则为 optionssource 成员。

    否则,

    为与 Document 关联WindowscrollingElement

  3. timelineaxis 属性设置为 options 的对应值。

如果 sourceScrollTimeline 是其 主盒 不存在的元素, 或不为 滚动容器, 或不存在 可滚动溢出, 则 ScrollTimeline 处于 非活动状态

ScrollTimeline持续时间 为 100%。

sourcecurrentTime 都在请求或更新时计算。

2.3. 命名滚动进度时间线

滚动进度时间线 也可以在 滚动容器 本身上定义, 然后在名称作用域内的元素中通过名称引用 (参见 § 4.2 命名时间线作用域和查找)。

这种 命名滚动进度时间线协调值列表 中声明,该列表由 长手写形式 构成,并与 scroll-timeline 简写属性 一起形成 协调列表属性组, 其中 scroll-timeline-name协调列表基础属性。 参见 CSS Values 4 § A 协调列表值属性

2.3.1. 为滚动进度时间线命名:scroll-timeline-name 属性

名称: scroll-timeline-name
值: none | <dashed-ident>#
初始值: none
适用于: 所有元素
继承:
百分比: n/a
计算值: 关键词 none 或 CSS 标识符列表
规范顺序: 按语法
动画类型: 不可动画

指定与此元素关联的 命名滚动进度时间线 的名称。

2.3.2. 滚动进度时间线的轴:scroll-timeline-axis 属性

名称: scroll-timeline-axis
值: [ block | inline | x | y ]#
初始值: block
适用于: 所有元素
继承:
百分比: n/a
计算值: 指定的关键字列表
规范顺序: 按语法
动画类型: 不可动画

指定由此 命名滚动进度时间线 来源的滚动轴 滚动容器。 如果此盒子不是 滚动容器, 则相应的 命名滚动进度时间线非活动状态

值定义与 scroll() 相同。

2.3.3. 滚动时间线简写:scroll-timeline 简写

名称: scroll-timeline
值: [ <'scroll-timeline-name'> <'scroll-timeline-axis'>? ]#
初始值: 见各个属性
适用于: 所有元素
继承:
百分比: 见各个属性
计算值: 见各个属性
动画类型: 不可动画
规范顺序: 按语法

此属性是设置 scroll-timeline-namescroll-timeline-axis简写 属性。

3. 视图进度时间线

通常希望动画在特定盒子(即 视图进度对象) 进入或离开视图时开始或结束, 而该部分视图正处于 滚动进度时间线 中。 视图进度时间线 是滚动进度时间线的 一部分,限定于视图中主体元素的任意部分(即 主盒) 与最近的祖先 滚动端口 相交时的滚动位置 (或更准确地说,是该 滚动端口视图进度可见范围)。 最早的这种滚动位置代表 0% 进度, 最晚的这种滚动位置代表 100% 进度; 参见 § 3.2 计算视图进度时间线的进度

注意: 0% 和 100% 滚动位置并不总是可以到达, 例如,如果盒子位于 可滚动溢出矩形 的起始边缘, 则可能无法滚动到小于 32% 进度的位置。

视图进度时间线 可以通过 view() 函数表示法 匿名引用,也可以在使用 view-timeline 属性声明后按名称引用 (参见 § 4.2 命名时间线作用域和查找)。 在 Web Animations API 中, 它们可以由 ViewTimeline 对象匿名表示。

3.1. 视图进度时间线范围

视图进度时间线 定义了以下 命名时间线范围

覆盖
表示整个 视图进度时间线 的范围:
包含
表示在其 视图进度可见范围 内,元素的 主盒 要么完全包含, 要么完全覆盖的范围。
进入
表示元素的 主盒 进入 视图进度可见范围 的范围。
  • 0% 等同于 覆盖 范围的 0%。

  • 100% 等同于 包含 范围的 0%。

退出
表示元素的 主盒 退出 视图进度可见范围 的范围。
  • 0% 等同于 包含 范围的 100%。

  • 100% 等同于 覆盖 范围的 100%。

进入交叉
表示元素的 主盒 穿过其 结束 边框边缘 的范围。
退出交叉
表示元素的 主盒 穿过其 起始 边框边缘 的范围。

插入图示。

在所有情况下,解析 起始结束 边缘时使用的 书写模式 是相关 滚动容器书写模式变换 被忽略, 但 相对绝对 定位 被考虑在内。

注意: 对于 粘性定位的盒子,0% 和 100% 进度条件有时可以通过一系列滚动位置来满足, 而不仅仅是一个位置。 每个范围因此指示是使用最早还是最晚的符合条件的位置。

[CSS-POSITION-3] [CSS-TRANSFORMS-1]

3.2. 计算视图进度时间线的进度

当前时间 中,视图进度时间线 的进度计算为: 距离 ÷ 范围,其中:

如果 0% 和 100% 位置重合 (即公式中的分母为零), 则时间线为 非活动状态

分页媒体 中,视图进度时间线 如果引用文档视口, 也会处于 非活动状态

3.3. 匿名视图进度时间线

3.3.1. view() 表示法

view() 函数表示法可以用作 <single-animation-timeline> 的值, 用于 animation-timeline,并引用最近的祖先 滚动容器 的视图进度时间线。 其语法为:

<view()> = view( [ <axis> || <'view-timeline-inset'> ]? )

默认情况下,view() 引用的是 块轴; 与 scroll() 类似, 这一行为可以通过提供明确的 <axis> 值进行更改。

可选的 <'view-timeline-inset'> 值提供了 视图进度可见范围 的调整, 如 view-timeline-inset 中所定义。

每次使用 view() 都对应 Web Animations API 中的一个 ViewTimeline 实例, 即使多个元素使用 view() 以相同的参数引用同一个元素。

3.3.2. ViewTimeline 接口

dictionary ViewTimelineOptions {
  Element subject;
  ScrollAxis axis = "block";
  (DOMString or sequence<(CSSNumericValue or CSSKeywordValue)>) inset = "auto";
};

[Exposed=Window]
interface ViewTimeline : ScrollTimeline {
  constructor(optional ViewTimelineOptions options = {});
  readonly attribute Element subject;
  readonly attribute CSSNumericValue startOffset;
  readonly attribute CSSNumericValue endOffset;
};

A ViewTimeline 是一个 AnimationTimeline ,用于指定 视图进度时间轴。 它可以传递给 Animation 构造函数或 animate() 方法,将动画链接到 视图进度时间轴

subject, 类型为 Element,只读

定义了时间轴进度的元素,其 主框滚动视口 中的可见性。

startOffset, 类型为 CSSNumericValue,只读

表示视图进度时间轴的起始 (0% 进度) 滚动位置,作为从 滚动起点 的长度偏移量 (以 px 为单位)。 时间轴为 非活动 时为空值。

endOffset, 类型为 CSSNumericValue,只读

表示视图进度时间轴的结束 (100% 进度) 滚动位置,作为从 滚动起点 的长度偏移量 (以 px 为单位)。 时间轴为 非活动 时为空值。

注意: startOffsetendOffset 的值相对于 滚动起点,而不是 物理 左上角。 根据 书写模式,它们可能与 scrollLeftscrollTop 的值不匹配,例如在右到左 ( rtl ) 书写模式 中的水平轴。

继承属性:

source (继承自 ScrollTimeline)

subject 的最近祖先,其 主框 创建了一个 滚动容器, 其滚动位置决定了时间轴的进度。

axis (继承自 ScrollTimeline)

指定滚动的轴线, 该轴线决定时间轴的进度。 请参见 <axis>,如上所述。

currentTime (继承自 AnimationTimeline)

表示 视图进度时间轴 的当前进度,百分比为 CSSUnitValue, 代表其 滚动容器 在当前位置的滚动进度。 当时间轴 非活动 时为 Null。

ViewTimeline(options)

使用以下步骤创建一个新的 ViewTimeline 对象:

  1. timeline 为新的 ViewTimeline 对象。

  2. subjectaxis 属性设置为 options 中的相应值。

  3. source 设置为 subject 的最近祖先 滚动容器 元素。

  4. 如果提供了 DOMString 作为 inset,则将其解析为 <'view-timeline-inset'> 值; 如果提供了序列, 第一个值表示起始插入,第二个值表示结束插入。 如果序列只有一个值, 则将其复制。 如果值为零或超过两个,或如果包含 CSSKeywordValuevalue 不是 "auto",则抛出 TypeError

    这些插入定义了 ViewTimeline视图进度可见范围

如果 sourcesubjectViewTimeline 是一个元素,其 主框 不存在, 或者如果它的最近祖先 滚动容器 没有 可滚动溢出(或没有此类祖先,例如在打印媒体中), 则 ViewTimeline非活动

当任何一个属性被请求或更新时,subjectsourcecurrentTime 的值都将被计算。

3.4. 命名视图进度时间轴

视图进度时间轴 也可以通过声明的方式定义, 然后由名字作用域内的元素引用 (参见 § 4.2 命名时间轴作用域和查找)。

这样的 命名视图进度时间轴协调值列表 中声明, 该列表由 view-timeline-* 属性构建, 这些属性形成一个 协调列表属性组,其中 view-timeline-name协调列表基础属性。 参见 CSS Values 4 § A 协调列表值属性

3.4.1. 命名视图进度时间轴:view-timeline-name 属性

名称: view-timeline-name
值: none | <dashed-ident>#
初始值: none
适用于: 所有元素
继承属性: no
百分比值: 不适用
计算值: 关键词 noneCSS标识符 列表
规范顺序: 根据语法
动画类型: 不可动画

为与该元素关联的 命名视图进度时间轴 指定名称。

3.4.2. 视图进度时间轴的轴线:view-timeline-axis 属性

名称: view-timeline-axis
值: [ block | inline | x | y ]#
初始值: block
适用于: 所有元素
继承属性: no
百分比值: 不适用
计算值: 指定的关键词列表
规范顺序: 根据语法
动画类型: 不可动画

指定从此元素的 命名视图进度时间轴 派生的轴线。 值的定义与 view() 相同。

3.4.3. 视图进度时间轴的插入: view-timeline-inset 属性

名称: view-timeline-inset
值: [ [ auto | <length-percentage> ]{1,2} ]#
初始值: auto
适用于: 所有元素
继承属性: no
百分比值: 相对于相关滚动端口的相应尺寸
计算值: 一对两值列表,表示起始和结束插入值,每个值可以是 auto 或计算的 length-percentage
规范顺序: 根据语法
动画类型: 按计算值类型

当确定是否将框视为视图中的内容时,指定滚动端口的插入(正值)或超出(负值)调整, 用于设置对应的 视图进度时间轴 的界限。 第一个值表示相关轴线上的 起始插入; 第二个值表示 结束 插入。 如果省略第二个值,则它被设置为第一个值。 结果范围是 视图进度可见性范围

auto
表示使用 scroll-padding 的值。
<length-percentage>
类似 scroll-padding, 定义从滚动端口相应边缘的内偏移量。

3.4.4. 视图时间轴速记: view-timeline 速记

名称: view-timeline
值: [ <'view-timeline-name'> <'view-timeline-axis'>? ]#
初始值: 参见各个属性
适用于: 所有元素
继承属性: 参见各个属性
百分比值: 参见各个属性
计算值: 参见各个属性
动画类型: 参见各个属性
规范顺序: 根据语法

此属性是 速记,用于在一个声明中设置 view-timeline-nameview-timeline-axis。 它不会设置 view-timeline-inset

是否也应重置 view-timeline-inset

4. 将动画附加到 滚动驱动时间轴

可以使用 滚动驱动时间轴 将动画附加到 scroll-timeline 属性(在CSS中) 或者 AnimationTimeline 参数(在Web动画API中)。 它们的 活动区间 附加的时间轴范围也可以进一步限制到特定的时间轴范围 (参见 将动画附加到时间轴范围)。

时间延迟(animation-delay) 不适用于 滚动驱动的动画, 它们是基于距离的。

4.1. 有限时间轴计算

与时间驱动的时间轴不同,滚动驱动的时间轴是有限的,因此滚动驱动的动画总是附加到有限的附加范围上——该范围可能会通过animation-range进一步限制(参见附录A:时间轴范围)。 动画的

iterations (animation-iteration-count) 在此有限范围内设置。如果指定的持续时间是auto, 那么将通过其迭代次数(animation-iteration-count) 来划分剩余的范围以找到已用持续时间。

注意:如果动画具有无限的迭代次数,那么每个迭代持续时间——以及生成的活动持续时间——将为零。

包含绝对定位关键帧的动画(那些固定在时间轴上的特定点上,例如在命名的时间轴范围关键帧选择器中使用的关键帧选择器)假设其迭代次数为1,以便找到这些关键帧相对于0%和100%的位置; 整个动画随后会缩放以适应迭代持续时间,并为每次迭代重复。

注意:目前尚不清楚将绝对定位关键帧与迭代次数超过1的情况组合在一起的用例是什么;这至少提供了一种定义的行为。 (另一种或许更奇怪的行为是将这些绝对定位的关键帧“移出流”,同时迭代其余的关键帧。) 编辑们对有关此处多次迭代的实际用例感兴趣。

4.2. 命名时间轴的范围和查找

命名的滚动进度时间轴视图进度时间轴可以被以下对象引用:

注意:timeline-scope属性可以用于在其定义元素的祖先上声明时间轴的名称,从而有效地将其范围扩展到该元素的子树之外。

如果多个元素声明了相同的时间轴名称,则匹配的时间轴是以树顺序声明在最近元素上的那个。如果在同一元素上发生名称冲突,则命名属性中声明较晚的名称(scroll-timeline-nameview-timeline-name)优先,并且滚动进度时间轴优先于视图进度时间轴

使用timeline-scope,一个元素可以引用绑定到兄弟、表亲甚至后代元素的时间轴。例如,以下代码创建了一个动画,该动画链接到由后续兄弟元素定义的滚动进度时间轴
<style>
  @keyframes anim {
    from { color: red; }
    to { color: green; }
  }

  .root {
    /* 声明 'scroller' 时间轴的范围以覆盖所有后代 */
    timeline-scope: scroller;
  }

  .root .animation {
    animation: anim;
    /* 引用 'scroller' 时间轴以驱动 'anim' 的进度 */
    animation-timeline: scroller;
  }

  .root .animation + .scroller {
    /* 附加一个滚动进度时间轴到时间轴名称 'scroller' */
    scroll-timeline: scroller;
  }
</style>
&hellip;
<section class="root">
  <div class="animation">Animating Box</div>
  <div class="scroller">Scrollable Box</div>
</section>

4.3. 动画事件

滚动驱动动画会分发与时间驱动动画相同的动画事件,正如在Web Animations § 4.4.18 动画事件CSS Animations 1 § 4 动画事件, 和CSS Animations 2 § 4.1 事件分发中描述的那样。

注意:当向后滚动时, animationstart事件将在活动间隔末尾触发, 而animationend事件将在活动间隔的开始触发。 然而,由于finish事件是关于进入已完成播放状态, 它只会在向前滚动时触发。

5. 帧计算细节

5.1. HTML处理模型:事件循环

滚动驱动动画的进度使得可能出现布局循环, 其中滚动偏移的变化会导致动画效果更新, 进而导致滚动偏移的再次变化。

为了避免这种布局循环, 使用滚动进度时间轴的动画在HTML处理模型事件循环的第7.10步期间更新它们的当前时间, 作为更新动画并发送事件的第1步。

HTML处理模型的第7.14.1步期间, 创建的任何滚动进度时间轴视图进度时间轴会被收集到一个过时时间轴集中。 在第7.14步之后,如果任何时间轴的命名时间轴范围发生了变化, 这些时间轴会被添加到过时时间轴集中。 如果存在任何过时时间轴,它们现在会更新它们的当前时间和相关范围, 过时时间轴集合被清空,我们会运行一个额外的步骤来重新计算样式并更新布局。

注意:在分发任何ResizeObserver之前我们故意检查布局变化, 以考虑程序化调整大小的元素。

注意:由于我们仅在第一次样式和布局计算期间收集过时时间轴, 这只能直接导致一次额外的样式重新计算。 其他需要进一步更新的API应在同一步骤中检查并同时更新。

注意:没有这个额外的样式和布局更新, 初始过时的时间轴将保持过时状态 (即它们不会有当前时间) 直到该帧的其余部分为止。 这意味着与该时间轴关联的动画在该帧不会产生任何效果值, 这可能导致渲染输出中出现不希望的初始"闪烁"。

注意:本节对由getComputedStyle()或类似方式触发的强制样式和布局计算没有影响。 换句话说,通过这些API可以看到初始过时的时间轴。

如果最终的样式和布局更新 会导致任何timeline-scope的时间或范围发生变化, 则这些滚动进度时间轴视图进度时间轴不会被重新采样以反映新的状态, 直到下次更新渲染时。

本节的内容无意要求滚动阻止布局或脚本。 如果用户代理通常在滚动发生后但滚动的后果尚未完全传播到布局或脚本中(例如scroll事件监听器尚未运行)合成帧, 用户代理可以选择不为该合成帧采样滚动驱动的动画。 在这种情况下,渲染的滚动偏移和滚动驱动动画的状态可能在合成帧中不一致。

6. 隐私考虑

本规范中的功能没有已知的隐私影响。

7. 安全考虑

本规范中的功能没有已知的安全影响。

附录A:时间轴范围

本节应移至CSS-ANIMATIONS-2和WEB-ANIMATIONS-2。

本附录将命名时间轴范围动画附着范围的概念引入了CSS动画Web动画

命名时间轴范围

命名时间轴范围是动画时间轴的命名片段。 该片段的开始表示为范围内的0%进度; 该片段的结束表示为范围内的100%进度。 多个命名时间轴范围可以与给定的时间轴关联, 多个范围可以重叠。 例如,视图进度时间轴contain范围与其cover范围重叠。命名时间轴范围<timeline-range-name>值类型表示, 它表示CSS标识符,用于代表一个预定义的命名时间轴范围

注意:在本规范中,命名时间轴范围必须由规范定义存在, 例如[SCROLL-ANIMATIONS-1]。 未来的级别可能会引入API,供作者声明他们自己的自定义命名时间轴范围

命名时间轴范围关键帧选择器

命名时间轴范围名称和百分比 可用于将关键帧附加到命名时间轴范围内的特定进度点。 CSS @keyframes规则进行了以下扩展:

<keyframe-selector> = from | to | <percentage [0,100]> | <timeline-range-name> <percentage>

其中,<timeline-range-name>是代表所选预定义命名时间轴范围CSS标识符, 而后面的<percentage>表示该命名时间轴范围的起始和结束之间的百分比进度。

关键帧被附加到时间轴中的指定点。 如果时间轴没有相应的命名时间轴范围, 那么附加到该命名时间轴范围上的任何关键帧都将被忽略。 这些附加点可能位于动画的活动间隔之外; 在这些情况下,只有在0%之前或100%之后(分别)的属性没有关键帧时,自动生成的from (0%) 和to (100%)关键帧 才会被生成。

将动画附加到时间轴范围

可以通过引用动画附加范围, 将一组动画关键帧附加到时间轴的某个范围内, 通过animation-range属性来限制动画的活动间隔。 延迟(请参阅animation-delay) 设置在这个限制范围内, 进一步减少了auto时长 和无限迭代的时间。

注意: animation-range可以扩展 附加范围,也可以缩小它。

任何位于附加范围之外的帧将根据需要用于插值, 但它们位于活动间隔之外,因此从动画本身中删除, 实际上在附加范围的末尾截断了动画。

range start┐             ╺┉┉active interval┉┉╸           ┌range end
┄┄┄┄┄┄┄┄┄┄┄├─────────────╊━━━━━━━━━━━━━━━━━━━╉───────────┤┄┄┄┄┄┄┄┄
           ╶┄start delay┄╴                   ╶┄end delay┄╴
                         ╶┄┄┄┄┄ duration┄┄┄┄┄╴

animation-range属性 是仅重置的子属性,属于animation简写属性。

定义其在时间驱动动画中的应用。

指定动画的时间轴范围:animation-range简写

名称: animation-range
值: [ <'animation-range-start'> <'animation-range-end'>? ]#
初始值: 参见各自属性
适用于: 参见各自属性
是否继承: 参见各自属性
百分比: 参见各自属性
计算值: 参见各自属性
动画类型: 参见各自属性
规范顺序: 按语法排列

animation-range属性是一个简写,它同时设置animation-range-startanimation-range-end,将动画与指定的动画附加范围关联。

如果<'animation-range-end'>被省略, 且<'animation-range-start'>包含<timeline-range-name>组件, 则animation-range-end设置为 相同的<timeline-range-name>100%。 否则,任何省略的长属性将设置为其初始值

以下声明集展示了animation-range简写声明, 以及其等效的animation-range-startanimation-range-end声明:
animation-range: entry 10% exit 90%;
animation-range-start: entry 10%;
animation-range-end: exit 90%;

animation-range: entry;
animation-range-start: entry 0%;
animation-range-end: entry 100%;

animation-range: entry exit;
animation-range-start: entry 0%;
animation-range-end: exit 100%;

animation-range: 10%;
animation-range-start: 10%;
animation-range-end: normal;

animation-range: 10% 90%;
animation-range-start: 10%;
animation-range-end: 90%;

animation-range: entry 10% exit;
animation-range-start: entry 10%;
animation-range-end: exit 100%;

animation-range: 10% exit 90%;
animation-range-start: 10%;
animation-range-end: exit 90%;

animation-range: entry 10% 90%;
animation-range-start: entry 10%;
animation-range-end: 90%;

如何处理省略值的默认处理?[Issue #8438]

指定动画的时间轴范围起点:animation-range-start 属性

名称: animation-range-start
值: [ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#
初始值: normal
适用于: 所有元素
是否继承:
百分比: 相对于指定的命名时间轴范围(如果已指定),否则相对于整个时间轴
计算值: 列表,每个项要么是关键字normal,要么是时间轴范围和进度百分比
规范顺序: 按语法排列
动画类型: 不可动画

指定动画的附加范围的起点, 相应地调整动画的开始时间 (即当迭代次数为1时,关键帧映射到0%进度的地方)。

值的含义如下:

normal
动画的附加范围的起点是其关联的时间轴的起点; 动画的活动 间隔按正常方式确定。
<length-percentage>
动画附加范围从指定的时间轴上的某个点开始, 从时间轴的起点开始测量。
<timeline-range-name> <length-percentage>?
动画附加范围从指定的命名时间轴范围的起点开始, 从该指定的命名时间轴范围开始测量。 如果省略了<length-percentage>, 它默认值为0%。

指定动画的时间轴范围终点:animation-range-end 属性

名称: animation-range-end
值: [ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#
初始值: normal
适用于: 所有元素
是否继承:
百分比: 相对于指定的命名时间轴范围(如果已指定),否则相对于整个时间轴
计算值: 列表,每个项要么是关键字normal,要么是时间轴范围和进度百分比
规范顺序: 按语法排列
动画类型: 不可动画

指定动画的附加范围的终点, 可能会调整动画的结束时间 (即当迭代次数为1时,关键帧映射到100%进度的地方), 并/或截短动画的活动间隔

值的含义如下:

normal
动画的附加范围的终点是其关联的时间轴的终点; 动画的活动 间隔按正常方式确定。
<length-percentage>
动画附加范围终止于指定的时间轴上的某个点, 从时间轴的起点开始测量。
<timeline-range-name> <length-percentage>?
动画附加范围终止于指定的命名时间轴范围的某个点, 从该指定的命名时间轴范围开始测量。 如果省略了<length-percentage>, 它的默认值为100%。

报告时间轴范围进度:getCurrentTime() 方法

命名范围的进度通过 AnimationTimeline 对象 通过 getCurrentTime() 方法暴露:

dictionary AnimationTimeOptions {
  DOMString? range;
};

[Exposed=Window]
partial interface AnimationTimeline {
  CSSNumericValue? getCurrentTime(optional AnimationTimeOptions options = {});
};
CSSNumericValue? getCurrentTime(optional AnimationCurrentTimeOptions = {})
返回当前时间的表示形式,具体如下:
如果没有提供 range
返回 currentTime 的值, 但表示为以 CSSUnitValue毫秒单位,而不是以双精度数。
如果提供了 range 并且是 命名时间轴范围的有效值:
progress 为该范围的当前进度, 以百分比值表示。

从 (progress, "percent") 创建一个 新的单位值 并返回它。

如果 命名时间轴范围 的起点和终点重合, 则返回时间值早于或等于该点的负无穷大, 以及之后的正无穷大。

如果提供了 range 但它不是有效的 命名时间轴范围
返回 null。

此方法与 currentTime 有关,但不完全相同;它是否应有一个不同的名称?[Issue #8201]

当提供范围名称时,此方法返回相对于 ScrollTimeline 范围的百分比。 但是对于基于时间的时间轴,如果提供了范围名称,它应该返回该范围内的百分比进度,还是时间进度?

附录 B:时间轴名称范围

本节应移至 CSS-ANIMATIONS-2。

本附录介绍了timeline-scope 属性, 它允许在时间轴定义元素的祖先上声明时间轴名称的范围。

声明命名时间轴的范围:timeline-scope 属性

Name: timeline-scope
Value: none | <dashed-ident>#
Initial: none
Applies to: 所有元素
Inherited: no
Percentages: n/a
Computed value: 关键字 none 或由 CSS标识符组成的列表
Canonical order: 根据语法排列
Animation type: 不可动画

此属性声明指定的时间轴名称的范围 扩展到此元素的子树中。 这允许命名的时间轴 (例如命名的滚动进度时间轴命名的视图进度时间轴) 可以被时间轴定义元素子树之外的元素引用,例如兄弟元素、堂兄元素或祖先元素。 它还阻止具有指定名称的子代时间轴 被外部子树引用, 并阻止具有指定名称的祖先时间轴 在此子树内被引用。

关于这些阻止效果还有一些开放讨论。[Issue #8915]

值的含义如下:

none
不改变时间轴名称的范围。
<dashed-ident>
声明由子代定义的匹配命名时间轴的名称—其范围未由子代使用 timeline-scope显式声明—适用于此元素及其子代的范围。

如果不存在这样的时间轴, 或者存在多个此类时间轴, 则声明具有指定名称的非活动时间轴

注意:此属性不能影响或使任何 时间轴名称查找失效 在声明相同名称的后代元素的子树内。 请参阅声明命名时间轴的范围:timeline-scope 属性

8. 更改

自上一个 (2023年4月28日) 工作草案以来的更改包括:

另请参阅更早的更改

合规性

文档约定

合规性要求通过描述性断言和RFC 2119术语的组合来表达。规范中的关键字“必须(MUST)”、“不得(MUST NOT)”、“必需(REQUIRED)”、“应当(SHALL)”、“不应当(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“可以(MAY)”和“可选(OPTIONAL)”应按照RFC 2119中的描述进行解释。然而,为了可读性,这些词语在本规范中并未全部以大写字母形式出现。

除非明确标记为非规范性部分,示例和注释,本文档的所有内容都是规范性的。[RFC2119]

本规范中的示例以“例如”开头,或者与规范文本分开显示,并使用class="example"样式展示,如下所示:

这是一个说明性的示例。

说明性注释以“注意”开头,并与规范文本分开显示,使用class="note"样式,如下所示:

注意,这是一个说明性注释。

通知部分是规范性的部分,通常以强调的样式呈现,使用这样:用户代理(UAs)必须(MUST)提供无障碍的替代方案。

合规性类别

合规性定义包括以下三类:

样式表
一种CSS样式表
渲染器
一种用户代理(UA),它解释样式表的语义并渲染使用它们的文档。
创作工具
一种用户代理(UA),用于编写样式表。

如果样式表的所有语句使用此模块定义的语法是有效的,并符合此模块中的每个功能的语法,则该样式表符合本规范。

如果渲染器不仅按照适用的规范解释样式表,还支持本规范中定义的所有功能,并正确解析它们并相应地渲染文档,则该渲染器符合本规范。然而,因设备限制导致用户代理无法正确渲染文档的情况,并不意味着用户代理不符合规范。(例如,用户代理不要求在单色显示器上呈现颜色。)

如果创作工具编写的样式表在语法上是正确的,并且符合此模块中的通用CSS语法和每个功能的语法要求,并符合本模块中描述的样式表的所有其他合规性要求,则该创作工具符合本规范。

部分实现

为了让作者能够利用向前兼容的解析规则分配备用值,CSS渲染器必须将任何无法使用的语法结构(包括@规则、属性、属性值、关键字等)视为无效的,并适当忽略。特别是,用户代理不得选择性地忽略无效的组件值,而只接受多值属性声明中的支持值:如果任何值被认为是无效的(因为不支持的值必须被视为无效),CSS要求整个声明被忽略。

不稳定和专有功能的实现

为了避免与未来的稳定CSS功能发生冲突,CSS工作组建议遵循最佳实践,以实现不稳定的功能和专有扩展

非实验性实现

一旦规范达到候选推荐标准阶段,就可以进行非实验性的实现,并且实现者应发布任何已正确实现并符合规范的CR级功能的非前缀实现。

为了建立并保持CSS在不同实现之间的互操作性,CSS工作组请求非实验性的CSS渲染器在发布任何CSS功能的非前缀实现之前,向W3C提交实现报告(如果需要,提交该实现报告所使用的测试用例)。提交给W3C的测试用例将由CSS工作组审查和修正。

有关提交测试用例和实现报告的更多信息,请访问CSS工作组网站:https://www.w3.org/Style/CSS/Test/。问题应发送到public-css-testsuite@w3.org邮件列表。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS Box Alignment Module Level 3. 2023年2月17日. WD. URL: https://www.w3.org/TR/css-align-3/
[CSS-ANIMATIONS-1]
David Baron; et al. CSS Animations Level 1. 2023年3月2日. WD. URL: https://www.w3.org/TR/css-animations-1/
[CSS-ANIMATIONS-2]
David Baron; Brian Birtles. CSS Animations Level 2. 2023年3月2日. WD. URL: https://www.w3.org/TR/css-animations-2/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. 2022年11月3日. WD. URL: https://www.w3.org/TR/css-box-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 2022年1月13日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. 2023年3月30日. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. 2023年3月29日. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS Positioned Layout Module Level 3. 2023年4月3日. WD. URL: https://www.w3.org/TR/css-position-3/
[CSS-SCOPING-1]
Tab Atkins Jr.; Elika Etemad. CSS Scoping Module Level 1. 2014年4月3日. WD. URL: https://www.w3.org/TR/css-scoping-1/
[CSS-SCROLL-SNAP-1]
Matt Rakow; et al. CSS Scroll Snap Module Level 1. 2021年3月11日. CR. URL: https://www.w3.org/TR/css-scroll-snap-1/
[CSS-SHAPES-2]
CSS Shapes Module Level 2 URL: https://drafts.csswg.org/css-shapes-2/
[CSS-TYPED-OM-1]
Shane Stephens; Tab Atkins Jr.; Naina Raisinghani. CSS Typed OM Level 1. 2018年4月10日. WD. URL: https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. 2022年12月1日. CR. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 2023年4月6日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. 2019年7月30日. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011年6月7日. REC. URL: https://www.w3.org/TR/CSS21/
[CSSOM-VIEW-1]
Simon Pieters. CSSOM View Module. 2016年3月17日. WD. URL: https://www.w3.org/TR/cssom-view-1/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[MEDIAQUERIES-5]
Dean Jackson; et al. Media Queries Level 5. 2021年12月18日. WD. URL: https://www.w3.org/TR/mediaqueries-5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEB-ANIMATIONS-1]
Brian Birtles; et al. Web Animations. 2022年9月8日. WD. URL: https://www.w3.org/TR/web-animations-1/
[WEB-ANIMATIONS-2]
Brian Birtles; Robert Flack. Web Animations Level 2. 2023年2月21日. WD. URL: https://www.w3.org/TR/web-animations-2/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

参考性引用

[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS Transforms Module Level 1. 2019年2月14日. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021年8月26日. WD. URL: https://www.w3.org/TR/cssom-1/
[RESIZE-OBSERVER-1]
Aleks Totic; Greg Whitworth. Resize Observer. 2020年2月11日. WD. URL: https://www.w3.org/TR/resize-observer-1/
[SCROLL-ANIMATIONS-1]
Brian Birtles; et al. Scroll-driven Animations. 2023年4月28日. WD. URL: https://www.w3.org/TR/scroll-animations-1/

属性索引

名称 初始值 适用对象 继承性 百分比 动画类型 规范顺序 计算值
animation-range [ <'animation-range-start'> <'animation-range-end'>? ]# 见个别属性 见个别属性 见个别属性 见个别属性 见个别属性 按语法 见个别属性
animation-range-end [ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]# normal 所有元素 相对于指定的命名时间轴范围,如果未指定,则相对于整个时间轴 不可动画 按语法 列表,每个项要么是关键词 normal,要么是时间轴范围和进度百分比
animation-range-start [ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]# normal 所有元素 相对于指定的命名时间轴范围,如果未指定,则相对于整个时间轴 不可动画 按语法 列表,每个项要么是关键词 normal,要么是时间轴范围和进度百分比
scroll-timeline [ <'scroll-timeline-name'> <'scroll-timeline-axis'>? ]# 见个别属性 所有元素 见个别属性 不可动画 按语法 见个别属性
scroll-timeline-axis [ block | inline | x | y ]# block 所有元素 不适用 不可动画 按语法 所指定的关键字列表
scroll-timeline-name none | <dashed-ident># none 所有元素 不适用 不可动画 按语法 关键词 none 或 CSS 标识符列表
timeline-scope none | <dashed-ident># none 所有元素 不适用 不可动画 按语法 关键词 none 或 CSS 标识符列表
view-timeline [ <'view-timeline-name'> <'view-timeline-axis'>? ]# 见个别属性 所有元素 见个别属性 见个别属性 见个别属性 按语法 见个别属性
view-timeline-axis [ block | inline | x | y ]# block 所有元素 不适用 不可动画 按语法 所指定的关键字列表
view-timeline-inset [ [ auto | <length-percentage> ]{1,2} ]# auto 所有元素 相对于相关滚动端口的相应维度 按计算值类型 按语法 由两个值对组成的列表,分别表示开始和结束插入的值,每个值要么是关键词 auto,要么是计算出的 <length-percentage> 值
view-timeline-name none | <dashed-ident># none 所有元素 不适用 不可动画 按语法 关键词 none 或 CSS 标识符列表

IDL 索引

enum ScrollAxis {
  "block",
  "inline",
  "x",
  "y"
};

dictionary ScrollTimelineOptions {
  Element? source;
  ScrollAxis axis = "block";
};

[Exposed=Window]
interface ScrollTimeline : AnimationTimeline {
  constructor(optional ScrollTimelineOptions options = {});
  readonly attribute Element? source;
  readonly attribute ScrollAxis axis;
};

dictionary ViewTimelineOptions {
  Element subject;
  ScrollAxis axis = "block";
  (DOMString or sequence<(CSSNumericValue or CSSKeywordValue)>) inset = "auto";
};

[Exposed=Window]
interface ViewTimeline : ScrollTimeline {
  constructor(optional ViewTimelineOptions options = {});
  readonly attribute Element subject;
  readonly attribute CSSNumericValue startOffset;
  readonly attribute CSSNumericValue endOffset;
};

dictionary AnimationTimeOptions {
  DOMString? range;
};

[Exposed=Window]
partial interface AnimationTimeline {
  CSSNumericValue? getCurrentTime(optional AnimationTimeOptions options = {});
};

问题索引

虽然 0% 通常表示 滚动容器 的初始滚动位置, 但根据其 内容分布,这可能并不成立。 请参见 CSS Box Alignment 3 § 5.3 溢出和滚动位置。 这是我们想要的吗?
添加关于 currentTime 是否可以为负值或大于 100% 的说明。
插入图表。
它是否还应重置 view-timeline-inset
该部分应移至 CSS-ANIMATIONS-2 和 WEB-ANIMATIONS-2。
定义时间驱动动画的应用。
在此处处理省略值默认情况的最佳方法是什么?[Issue #8438]
此方法与 currentTime 有关,但不完全相同;它应该有不同的名称吗?[Issue #8201]
当提供了范围名称时,此方法返回相对于 ScrollTimeline 范围的百分比。 但对于基于时间的时间轴,如果提供了范围名称, 它应该返回该范围内的百分比进度,还是该范围内的时间进度?
此部分应移至 CSS-ANIMATIONS-2。
关于这些阻断效果的讨论仍在进行中。[Issue #8915]