CSS 动画第 1 级

W3C 工作草案,

关于此文档的更多细节
此版本
https://w3org.cn/TR/2023/WD-css-animations-1-20230302/
最新发布版本
https://w3org.cn/TR/css-animations-1/
编辑草案
https://drafts.csswg.org/css-animations/
历史版本
历史
https://w3org.cn/standards/history/css-animations-1
测试套件
http://test.csswg.org/suites/css-animations-1_dev/nightly-unstable/
反馈
CSS 工作组问题仓库
文档内联
编辑
(Apple Inc.)
L. David Baron (Google)
Tab Atkins Jr. (Google)
(受邀专家)
前任编辑
David Hyatt (Apple Inc.)
Chris Marrin (Apple Inc.)
(Adobe)
建议编辑此规范
GitHub 编辑器
问题列表
https://github.com/w3c/csswg-drafts/labels/css-animations-1

摘要

本 CSS 模块描述了一种供作者使用关键帧随时间改变 CSS 属性值的方法。这些关键帧动画的行为可以通过指定其持续时间、重复次数和重复行为来进行控制。

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

关于本文档

本部分描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新版本可在 W3C 技术报告索引(https://w3org.cn/TR/)中找到。

本文件由 CSS 工作组推荐标准轨道 (Recommendation track) 下的 工作草案 (Working Draft) 形式发布。以工作草案形式发布并不代表 W3C 及其成员的认可。

这是一份草案文档,可能会随时被其他文档更新、替换或废弃。将其作为非进行中工作引用是不恰当的。

请通过在 GitHub 上提交 issue(首选)来发送反馈,并在标题中包含规范代码 “css-animations”,格式如下:“[css-animations] …评论摘要…”。所有问题和评论均已存档。此外,也可以将反馈发送至(已存档的)公共邮件列表 www-style@w3.org

本文档受 2021 年 11 月 2 日版 W3C 流程文档管辖。

本文档由在 W3C 专利政策下运作的组织制作。W3C 维护一份与该组织交付成果相关的 公开专利披露列表;该页面还包含披露专利的说明。任何知悉其认为包含 必要权利要求 的专利的个人,必须按照 W3C 专利政策第 6 节披露该信息。

1. 简介

本节是非规范性的

CSS 过渡 [CSS3-TRANSITIONS] 提供了一种在底层属性变化导致 CSS 属性值变化时对其进行插值的方法。这提供了一种实现简单动画的便捷方式,但动画的开始和结束状态由现有的属性值控制,且过渡无法为作者提供多少关于动画进度方面的控制。

本提案引入了定义好的动画,作者可以将 CSS 属性随时间的变化指定为一组关键帧。动画与过渡类似,它们都是随时间改变 CSS 属性的表现值。主要区别在于:过渡在属性值发生变化时隐式触发,而动画在应用动画属性时显式执行。正因如此,动画需要为被动画化的属性指定显式值。这些值使用下面描述的动画关键帧来指定。

动画的许多方面都可以控制,包括动画循环的次数、是否在开始值和结束值之间交替,以及动画是应该运行还是暂停。动画还可以延迟其开始时间。

1.1. 值定义

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

除了定义中列出的属性特定值外,本规范中定义的所有属性也都接受 CSS 全局关键字 作为其属性值。为了可读性,未明确重复列出。

2. 动画

CSS 动画会影响计算后的属性值。这种效果是通过向 CSS 层叠中添加一个指定值 ([CSS3CASCADE])(在 CSS 动画层级)来实现的,该值会为动画的当前状态产生正确的计算值。如 [CSS3CASCADE] 中所定义,动画覆盖所有常规规则,但被 !important 规则所覆盖。

如果某个时间点有多个动画为同一属性指定了行为,则在 animation-name 值中排在最后的动画将覆盖该点处的其他动画。

动画在应用之前(即当元素上设置了 animation-name 属性时)或移除之后,不会影响其计算值。此外,通常情况下,动画在动画延迟过期之前或动画结束后不会影响计算值,但根据 animation-fill-mode 属性可能会有所不同。

在运行时,动画会计算其所动画化属性的值。根据 CSS 层叠 ([CSS3CASCADE]),其他值可能会优先于动画值。

当动画已应用但尚未结束,或者已结束但具有 animation-fill-modeforwardsboth 时,用户代理必须表现得好像元素上的 will-change 属性 ([css-will-change-1]) 额外包含了该动画所动画化的所有属性。

动画的开始时间是应用动画的样式和相应的 @keyframes 规则都解析完成的时间。如果为元素指定了动画,但相应的 @keyframes 规则尚不存在,则动画无法开始;一旦能解析到匹配的 @keyframes 规则,动画将从头开始。通过动态修改元素样式指定的动画将在该样式解析时开始;在伪样式规则(如 hover)的情况下可能是立即开始,或者在脚本应用样式的情况下是脚本引擎将控制权交还给浏览器时开始。请注意,动态更新关键帧样式规则不会启动或重新启动动画。

如果一个动画的名称作为标识符出现在 animation-name 属性的计算值中,并且该动画使用有效的 @keyframes 规则,则它应用于该元素。一旦动画开始,它就会持续到结束或 animation-name 被移除。在动画运行时更改动画属性的值,其应用方式如同动画自始至终都具有这些值一样。例如,缩短 animation-delay 可能会导致动画向前跳跃,甚至立即结束并派发 animationend 事件。相反,延长 animation-delay 可能会导致动画重新开始并派发 animationstart 事件。

同一个 @keyframes 规则名称可以在 animation-name 中重复。对 animation-name 的更改会通过从后往前遍历新的动画列表来更新现有动画,并为每个动画在现有动画列表中找到最后一个匹配的动画。如果找到匹配项,则使用对应于其在新的动画列表中位置的动画属性来更新现有动画,同时如上所述保持其当前的播放时间。匹配的动画将从现有动画列表中移除,这样它就不会被匹配两次。如果没有找到匹配项,则创建一个新动画。因此,将 animation-name 从 ‘a’ 更新为 ‘a, a’ 将导致 ‘a’ 的现有动画成为列表中的第二个动画,并为列表中的第一项创建一个新动画。

div {
  animation-name: diagonal-slide;
  animation-duration: 5s;
  animation-iteration-count: 10;
}

@keyframes diagonal-slide {

  from {
    left: 0;
    top: 0;
  }

  to {
    left: 100px;
    top: 100px;
  }

}

这将产生一个动画,将元素在五秒内从 (0, 0) 移动到 (100px, 100px),并重复九次(总共十次迭代)。

display 属性设置为 none 将终止应用于该元素及其后代的任何正在运行的动画。如果元素的 displaynone,则将 display 更新为非 none 的值将启动由 animation-name 属性应用于该元素的所有动画,以及所有应用于 displaynone 的后代的动画。

虽然作者可以使用动画来创建动态变化的内容,但动态变化的内容可能会导致部分用户癫痫发作。有关如何避免可能导致癫痫发作的内容的信息,请参阅指南 2.3:癫痫发作:不要以已知会导致癫痫发作的方式设计内容 ([WCAG20])。

当渲染媒介不是交互式时(例如打印时),实现可以忽略动画。本规范的未来版本可能会定义如何为这些媒介渲染动画。

3. 关键帧

关键帧用于指定动画化属性在动画过程中各个点的取值。关键帧指定了一个动画周期内的行为;动画可以迭代零次或多次。

关键帧使用 @keyframes at-rule 进行指定,定义如下

@keyframes = @keyframes <keyframes-name> { <rule-list> }

<keyframes-name> = <custom-ident> | <string>

<keyframe-block> = <keyframe-selector># { <declaration-list> }

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

@keyframes 内部的 <rule-list> 只能包含 <keyframe-block> 规则。

<keyframe-block> 内部的 <declaration-list> 接受除本规范定义的属性之外的任何 CSS 属性,但它确实接受 animation-timing-function 属性并对其进行特殊解析。没有任何属性会与层叠交互(因此在它们上面使用 !important 是无效的,会导致该属性被忽略)。

@keyframes 块具有一个名称,由其序言中的 <custom-ident><string> 给定。两种语法在功能上是等价的;名称即 ident 或 string 的值。正如 <custom-ident><string> 的常规情况一样,名称完全区分大小写;仅当两个名称逐个代码点相等时才相等。<custom-ident> 此外排除了 none 关键字。

例如,以下两个 @keyframes 规则具有相同的名称,因此第一个将被忽略
@keyframes foo { /* ... */ }
@keyframes "foo" { /* ... */ }

另一方面,以下 @keyframes 规则的名称与前两个规则不同

@keyframes FOO { /* ... */ }

以下 @keyframes 规则无效,因为它们使用了不允许的 <custom-ident>

@keyframes initial { /* ... */ }
@keyframes None { /* ... */ }

然而,这些名称可以使用 <string> 指定,因此以下内容均有效

@keyframes "initial" { /* ... */ }
@keyframes "None" { /* ... */ }

<keyframe-selector> 对于 <keyframe-block> 由逗号分隔的百分比值列表或关键字 fromto 组成。选择器用于指定关键帧在动画持续时间中所处的百分比。关键帧本身由在选择器上声明的属性值块指定。关键字 from 等同于值 0%。关键字 to 等同于值 100%。小于 0% 或大于 100% 的值无效,并会导致其 <keyframe-block> 被忽略。

请注意,百分比值必须使用百分比单位说明符。因此,0 是无效的关键帧选择器。

如果未指定 0%from 关键帧,则用户代理使用被动画化属性的计算值构建 0% 关键帧。如果未指定 100%to 关键帧,则用户代理使用被动画化属性的计算值构建 100% 关键帧。

<keyframe-block> 包含属性和值。本规范定义的属性在这些规则中会被忽略,但 animation-timing-function 除外,其行为如下所述。此外,被 !important 修饰的属性无效并被忽略。

如果定义了多个名称相同的 @keyframes 规则,文档流中最后的规则胜出,所有之前的规则都被忽略。

div {
  animation-name: slide-right;
  animation-duration: 2s;
}

@keyframes slide-right {

  from {
    margin-left: 0px;
  }

  50% {
    margin-left: 110px;
    opacity: 1;
  }

  50% {
    opacity: 0.9;
  }

  to {
    margin-left: 200px;
  }

}

上面提到的两个 50% 规则也可以合并为一个等价的单一规则,如下所示

@keyframes slide-right {

  from {
    margin-left: 0px;
  }

  50% {
    margin-left: 110px;
    opacity: 0.9;
  }

  to {
    margin-left: 200px;
  }

}

为了确定关键帧集合,选择器中的所有值都会按时间增加的顺序进行排序。然后 @keyframes 规则内部的规则会进行层叠;因此,关键帧的属性可能派生自多个具有相同选择器值的 @keyframes 规则。

如果未为关键帧指定属性,或者指定了但无效,则该属性的动画将如同该关键帧不存在一样进行。在概念上,就像为存在于任何关键帧中的每个属性构建了一组关键帧,并为每个属性独立运行动画一样。

@keyframes wobble {
  0% {
    left: 100px;
  }

  40% {
    left: 150px;
  }

  60% {
    left: 75px;
  }

  100% {
    left: 100px;
  }
}

为名为 "wobble" 的动画指定了四个关键帧。在第一个关键帧(动画周期开始时)中,被动画化的 left 属性值为 100px。到动画持续时间的 40% 时,left 动画变为 150px。在动画持续时间的 60% 时,left 动画回到 75px。在动画周期结束时,left 的值已返回 100px。下方的图表展示了如果给予其 10s 持续时间后的动画状态。

关键帧指定的动画状态

本规范需要定义如何从关键帧确定值,就像 CSS 过渡的 过渡应用 一节所做的那样。

3.1. 关键帧的时间函数

关键帧样式规则还可以声明动画移动到下一个关键帧时所要使用的时间函数。

@keyframes bounce {

  from {
    top: 100px;
    animation-timing-function: ease-out;
  }

  25% {
    top: 50px;
    animation-timing-function: ease-in;
  }

  50% {
    top: 100px;
    animation-timing-function: ease-out;
  }

  75% {
    top: 75px;
    animation-timing-function: ease-in;
  }

  to {
    top: 100px;
  }

}

为名为 "bounce" 的动画指定了五个关键帧。在第一个和第二个关键帧之间(即 0% 和 25% 之间)使用了 ease-out 时间函数。在第二个和第三个关键帧之间(即 25% 和 50% 之间)使用了 ease-in 时间函数。以此类推。其效果表现为一个元素在页面上向上移动 50px,在到达最高点时减速,然后在掉回 100px 时加速。动画的后半部分表现类似,但只会将元素向上移动 25px。

to100% 关键帧上指定的时间函数会被忽略。

有关更多信息,请参阅 animation-timing-function 属性。

3.2. animation-name 属性

animation-name 属性定义了一个要应用的动画列表。每个名称都用于选择提供动画属性值的关键帧 at-rule。如果名称与任何关键帧 at-rule 不匹配,则没有要动画化的属性,动画将不会执行。此外,如果动画名称为 none,则不会有动画。这可用于覆盖来自层叠的任何动画。如果多个动画试图修改同一个属性,则名称列表中排在最后面的动画胜出。

列出的每个动画名称都应为下面列出的其他动画属性具有相应的值。如果其他动画属性的值列表长度不同,则 animation-name 列表的长度决定了启动动画时检查每个列表中的项数。列表从第一个值开始匹配:末尾多余的值不会被使用。如果其他属性之一没有足够的逗号分隔值来匹配 animation-name 的值的数量,则 UA 必须通过重复值列表直到有足够的数量来计算其使用值。这种截断或重复不会影响计算值。

注意:这类似于 background-* 属性的行为,其中 background-image 类似于 animation-name

名称animation-name
[ none | <keyframes-name> ]#
初始值 none(无)
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每项要么是一个区分大小写的 css 标识符,要么是关键字 none
规范顺序 按语法
动画类型 不可动画

animation-name 的值具有以下含义

none(无)
没有指定任何关键帧,因此不会有动画。为该动画指定的任何其他动画属性均无效。
<keyframes-name>
如果存在,动画将使用 <keyframes-name> 指定名称的关键帧。如果不存在该名称的 @keyframes 规则,则没有动画。

3.3. animation-duration 属性

animation-duration 属性定义单个动画周期的持续时间。

名称animation-duration
<time [0s,∞]>#
初始值 0s
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每项是一个持续时间
规范顺序 按语法
动画类型 不可动画
<time [0s,∞]>
<time> 指定动画完成一个周期所需的时间长度。负的 <time> 是无效的。

如果 <time>0s(初始值),则动画的关键帧不会有任何效果,但动画本身仍然会瞬间发生。具体而言,会触发开始和结束事件;如果 animation-fill-mode 设置为 backwardsboth,则动画的第一帧(由 animation-direction 定义)将在 animation-delay 期间显示。在 animation-delay 之后,如果 animation-fill-mode 设置为 forwardsboth,将显示动画的最后一帧(由 animation-direction 定义)。如果 animation-fill-mode 设置为 none,则动画将没有任何可见效果。

3.4. animation-timing-function 属性

animation-timing-function 属性描述了动画在每对关键帧之间将如何进行。时间函数定义在单独的 CSS Easing Functions 模块 [css-easing-1] 中。

使用的 输入进度值 是当前关键帧与下一个关键帧之间经过的时间百分比,合并了 animation-direction 属性的效果之后。

animation-delay 期间,animation-timing-function 不会被应用。

注意:此定义是必要的,否则具有 start 阶梯位置阶梯缓动函数 将产生等于函数中第一步顶部的反向填充。

输出进度值 在当前和下一个关键帧之间插值属性值时用作 p 值。

名称animation-timing-function
<easing-function>#
初始值 ease
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每项是一个计算后的 <easing-function>
规范顺序 按语法
动画类型 不可动画

当在关键帧中指定时,animation-timing-function 定义了动画在排序后的关键帧选择器顺序中,当前关键帧与下一个关键帧之间被动画化属性的进程(可能是一个隐式的 100% 关键帧)。

3.5. animation-iteration-count 属性

animation-iteration-count 属性指定了动画周期播放的次数。初始值为 1,意味着动画将从头到尾播放一次。此属性通常与值为 alternateanimation-direction 结合使用,这将导致动画在交替周期中反向播放。

动画处于活动状态的时间窗口(duration x iteration-count)被称为 活动持续时间

名称animation-iteration-count
<single-animation-iteration-count>#
初始值 1
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每项要么是一个数字,要么是关键字 infinite
规范顺序 按语法
动画类型 不可动画

<single-animation-iteration-count> = infinite | <number [0,∞]>

infinite
动画将无限重复。
<number [0,∞]>

动画将重复指定的次数。如果数字不是整数,动画将在其最后一个周期中途结束。负数是无效的。

值为 0 是有效的,类似于 0sanimation-duration,会导致动画瞬间发生。

如果动画的持续时间为 0s,则对于 animation-iteration-count 的任何有效值(包括 infinite),它都会瞬间发生。

3.6. animation-direction 属性

animation-direction 属性定义动画是否应在部分或全部周期内反向播放。当动画反向播放时,时间函数也会反转。例如,反向播放时,ease-in 动画看起来就像是一个 ease-out 动画。

名称animation-direction
<single-animation-direction>#
初始值 normal
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每一项均为指定的关键字
规范顺序 按语法
动画类型 不可动画

<single-animation-direction> = normal | reverse | alternate | alternate-reverse

normal
动画的所有迭代均按指定方式播放。
reverse
动画的所有迭代均以与指定方式相反的方向播放。
alternate
奇数次计数的动画周期迭代以正常方向播放,偶数次计数的动画周期迭代以相反方向播放。
alternate-reverse(交替反向)
奇数次计数的动画周期迭代以相反方向播放,偶数次计数的动画周期迭代以正常方向播放。

注意:出于确定迭代是奇数还是偶数的目的,迭代从 1 开始计数。

3.7. animation-play-state 属性

animation-play-state 属性定义动画是在运行还是已暂停。

名称animation-play-state
<single-animation-play-state>#
初始值 running
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每一项均为指定的关键字
规范顺序 按语法
动画类型 不可动画

<single-animation-play-state> = running | paused

running
当此属性设置为 running 时,动画按正常方式进行。
暂停 (paused)
当此属性设置为 paused 时,动画已暂停。动画继续应用于具有暂停前所取得进度的元素。当取消暂停时(设置回 running),它会从离开的地方重新开始,就像控制动画的“时钟”停止并再次启动一样。

如果在动画的延迟阶段属性被设置为 paused,延迟时钟也会暂停,并在 animation-play-state 被设置回 running 后立即恢复。

3.8. animation-delay 属性

animation-delay 属性定义动画何时开始。它允许动画在应用后一段时间开始执行,或者看起来在应用之前一段时间就已经开始执行。

名称animation-delay
<time>#
初始值 0s
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每项是一个持续时间
规范顺序 按语法
动画类型 不可动画
<time>
<time> 定义了动画开始(当通过这些属性将动画应用于元素时)与开始执行之间的延迟时间长度。0s 的延迟(初始值)意味着动画将在应用后立即执行。

负延迟是有效的。类似于 0s 的延迟,它意味着动画立即执行,但会被自动推进延迟的绝对值,如同动画在过去指定的某个时间点开始一样,因此它看起来像是从其 活动持续时间 的中途开始的。如果动画的关键帧具有隐含的起始值,则这些值取自动画开始的时间,而不是过去的某个时间。

3.9. animation-fill-mode 属性

animation-fill-mode 属性定义了在动画执行时间之外应用哪些值。默认情况下,动画不会影响动画应用时间(在元素上设置 animation-name 属性时)与开始执行时间(由 animation-delay 属性决定)之间的属性值。此外,默认情况下,动画在结束之后(由 animation-durationanimation-iteration-count 属性决定)也不会影响属性值。animation-fill-mode 属性可以覆盖此行为。对属性的动态更新将根据需要反映在属性值中,无论是在动画延迟期间还是在动画结束后。

名称animation-fill-mode
<single-animation-fill-mode>#
初始值 none(无)
应用于 所有元素
可继承
百分比 不适用
计算值 列表,每一项均为指定的关键字
规范顺序 按语法
动画类型 不可动画

<single-animation-fill-mode> = none | forwards | backwards | both

none(无)
动画在应用但未执行时没有效果。
forwards(向前)
动画结束后(由其 animation-iteration-count 决定),动画将应用动画结束时的属性值。当 animation-iteration-count 是大于零的整数时,应用的值将是动画最后一次完成迭代结束时的值(而不是下一次迭代开始时的值)。当 animation-iteration-count 为零时,应用的值将是开始第一次迭代时的值(就像 animation-fill-modebackwards 时一样)。
backwards(向后)
animation-delay 定义的期间,动画将应用动画第一次迭代开始时定义在关键帧中的属性值。这些值要么是 from 关键帧的值(当 animation-directionnormalalternate 时),要么是 to 关键帧的值(当 animation-directionreversealternate-reverse 时)。
both
forwardsbackwards 填充的效果同时应用。

3.10. animation 简写属性

animation 简写属性是一个逗号分隔的动画定义列表。列表中的每一项给出了该简写属性所有子属性(即动画属性)值中的一项。(有关当这些属性具有不同长度的列表时会发生什么,请参阅 animation-name 的定义,当使用 animation 简写属性定义时,此问题不会发生。)

名称animation
<single-animation>#
初始值 见各个属性
应用于 所有元素
可继承
百分比 不适用
计算值 见各个属性
规范顺序 按语法
动画类型 不可动画

<single-animation> = <time> || <easing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]

请注意,在每个动画定义中顺序很重要:每个 <single-animation> 中第一个可以解析为 <time> 的值被分配给 animation-duration,而每个 <single-animation> 中第二个可以解析为 <time> 的值被分配给 animation-delay

请注意,每个动画定义内部的顺序对于区分 <keyframes-name> 值与其他关键字也非常重要。解析时,对于那些值在简写属性中未更早出现的、除 animation-name 之外属性有效的关键字,必须接受用于这些属性而不是用于 animation-name。此外,序列化时,必须输出其他属性的默认值,至少在必要的情况下用于区分可能属于另一个属性值的 animation-name,在其他情况下也可以输出。

例如,从 animation: 3s none backwards 解析出的值(其中 animation-fill-modenoneanimation-namebackwards)不得序列化为 animation: 3s backwards(其中 animation-fill-modebackwardsanimation-namenone)。

4. 动画事件

通过 DOM 事件系统可以使用几个与动画相关的事件。动画的开始和结束,以及动画的每次迭代结束,都会生成 DOM 事件。一个元素可以同时有多个属性被动画化。这可以通过具有多个属性的关键帧的单个 animation-name 值,或者通过多个 animation-name 值来实现。就事件而言,每个 animation-name 指定一个单一动画。因此,事件将为每个 animation-name 值生成,而不一定为每个被动画化的属性生成。

任何定义了有效关键帧规则的动画都将运行并生成事件;这包括具有空关键帧规则的动画。

动画运行的时间随生成的每个事件一起发送。这允许事件处理器确定循环动画的当前迭代或交替动画的当前位置。此时间不包括动画处于 paused 播放状态的任何时间。

4.1. AnimationEvent 接口

AnimationEvent 接口提供与动画事件关联的具体上下文信息。

4.1.1. IDL 定义

[Exposed=Window]
interface AnimationEvent : Event {
  constructor(CSSOMString type, optional AnimationEventInit animationEventInitDict = {});
  readonly attribute CSSOMString animationName;
  readonly attribute double elapsedTime;
  readonly attribute CSSOMString pseudoElement;
};
dictionary AnimationEventInit : EventInit {
  CSSOMString animationName = "";
  double elapsedTime = 0.0;
  CSSOMString pseudoElement = "";
};

4.1.2. 属性

animationName, 类型为 CSSOMString, 只读
触发事件的动画的 animation-name 属性值。
elapsedTime, 类型为 double, 只读
事件触发时,动画已运行的时间量(以秒为单位),不包括动画暂停的任何时间。此成员的精确计算定义在每个事件类型中。
pseudoElement, 类型为 CSSOMString, 只读
动画在其上运行的 CSS 伪元素的名称(以两个冒号开头)(在这种情况下,事件的目标是该伪元素对应的元素),如果动画在元素上运行,则为空字符串(这意味着事件的目标是该元素)。

AnimationEvent(type, animationEventInitDict) 是一个 事件构造函数

4.2. AnimationEvent 的类型

可能发生的各类动画事件包括

animationstart
animationstart 事件发生在动画开始时。如果有 animation-delay,此事件将在延迟期满后触发一次。

负延迟将导致事件触发,其 elapsedTime 等于延迟的绝对值,并以动画的 活动持续时间 为上限,即 min(max(-animation-delay, 0), 活动持续时间);在这种情况下,无论 animation-play-state 设置为 running 还是 paused,事件都将触发。

  • 冒泡:是
  • 可取消:否
  • 上下文信息:animationName, elapsedTime, pseudoElement
animationend
animationend 事件发生在动画结束时。在这种情况下,事件的 elapsedTime 成员的值等于 活动持续时间
  • 冒泡:是
  • 可取消:否
  • 上下文信息:animationName, elapsedTime, pseudoElement
animationiteration
animationiteration 事件发生在动画每次迭代结束时,除非此时会触发 animationend 事件。这意味着此事件不会发生在迭代次数为一次或更少的动画中。

在这种情况下,elapsedTime 成员等于 当前迭代animation-duration 的乘积,其中 当前迭代 是新迭代的从零开始的索引。例如,假设没有负的 animation-delay,在一次迭代完成后,当前迭代 将为一。

  • 冒泡:是
  • 可取消:否
  • 上下文信息:animationName, elapsedTime, pseudoElement
animationcancel
animationcancel 事件发生在动画以不触发 animationend 事件的方式停止运行时,例如更改 animation-name 从而移除了动画,或者动画化元素或其祖先之一变为 display:none

此事件的 elapsedTime 成员表示动画取消时自动画开始以来经过的秒数。这不包括动画暂停的任何时间。如果动画具有负的 animation-delay,则动画开始的时刻等于动画实际触发之前 animation-delay 秒的绝对值。或者,如果动画具有正的 animation-delay 并且在动画延迟过期之前触发了事件,则 elapsedTime 将为零。

  • 冒泡:是
  • 可取消:否
  • 上下文信息:animationName, elapsedTime, pseudoElement

4.3. 元素、Document 对象和 Window 对象上的事件处理器

以下是所有 HTML 元素 必须支持的 事件处理器(及其对应的 事件处理器事件类型),既作为 事件处理器内容属性 也作为 事件处理器 IDL 属性;且必须由所有 DocumentWindow 对象作为 事件处理器 IDL 属性 支持。

事件处理器 事件处理器事件类型
onanimationstart animationstart
onanimationiteration animationiteration
onanimationend animationend
onanimationcancel animationcancel

5. DOM 接口

CSS 动画通过一对描述关键帧的新接口暴露给 CSSOM。

注意:下面定义的接口反映了截至本规范级别可用的互操作 API。未来的级别可能会弃用此 API 的部分内容并扩展其他内容。

5.1. CSSRule 接口

以下两种规则类型被添加到 CSSRule 接口中。它们为新的关键帧和关键帧规则提供了标识。

5.1.1. IDL 定义

partial interface CSSRule {
    const unsigned short KEYFRAMES_RULE = 7;
    const unsigned short KEYFRAME_RULE = 8;
};

5.2. CSSKeyframeRule 接口

CSSKeyframeRule 接口表示单个关键点的样式规则。

5.2.1. IDL 定义

[Exposed=Window]
interface CSSKeyframeRule : CSSRule {
  attribute CSSOMString keyText;
  [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
};

5.2.2. 属性

keyText, 类型为 CSSOMString
此属性将关键帧选择器表示为逗号分隔的百分比值列表。fromto 关键字分别映射到 0% 和 100%。

如果使用无效的关键帧选择器更新 keyText,则必须抛出 SyntaxError 异常,且 keyText 的值必须保持不变。

style, 类型为 CSSStyleDeclaration, 只读
必须返回关键帧规则的 CSSStyleDeclaration 对象,并具有以下属性
只读标志
未设置。
declarations
规则中声明的声明,按 指定顺序
父 CSS 规则
上下文对象(即此 CSSKeyframeRule)。
所有者节点
Null。

5.3. CSSKeyframesRule 接口

CSSKeyframesRule 接口表示单个动画的一组完整关键帧。

5.3.1. IDL 定义

[Exposed=Window]
interface CSSKeyframesRule : CSSRule {
           attribute CSSOMString name;
  readonly attribute CSSRuleList cssRules;
  readonly attribute unsigned long length;

  getter CSSKeyframeRule (unsigned long index);
  undefined        appendRule(CSSOMString rule);
  undefined        deleteRule(CSSOMString select);
  CSSKeyframeRule? findRule(CSSOMString select);
};

5.3.2. 属性

name, 类型为 CSSOMString
此属性是关键帧的名称,由 animation-name 属性使用。
cssRules, 类型为 CSSRuleList, 只读
此属性允许访问列表中的关键帧。
length, 类型为 unsigned long, 只读
此属性是列表中关键帧的数量。

5.3.3. 索引属性获取器

索引属性获取器 从关键帧列表中返回指定位置的 CSSKeyframeRule

参数

index 类型为 unsigned long
要返回规则的从零开始的索引。

返回值

CSSKeyframeRule
找到的规则,如果指定索引处没有规则,则为 undefined

无异常

5.3.4. appendRule 方法

appendRule 方法将传入的 CSSKeyframeRule 追加到关键帧规则的末尾。

参数

rule 类型为 CSSOMString
要追加的规则,以与 @keyframes 规则中单个条目相同的语法表示。有效规则总是会被追加,例如即使其关键帧选择器已存在。

无返回值

无异常

5.3.5. deleteRule 方法

deleteRule 方法删除匹配指定关键帧选择器的最后声明的 CSSKeyframeRule。如果没有匹配的规则,该方法不执行任何操作。

参数

select 类型为 CSSOMString
要删除规则的关键帧选择器:0% 到 100% 之间的逗号分隔百分比值列表,或分别解析为 0% 和 100% 的关键字 fromto

指定关键帧选择器中值的数量和顺序必须与目标关键帧规则的值匹配。匹配对列表值周围的空格不敏感。

无返回值

无异常

5.3.6. findRule 方法

findRule 返回匹配指定关键帧选择器的最后声明的 CSSKeyframeRule。如果没有匹配的规则,该方法不执行任何操作。

参数

select 类型为 CSSOMString
要查找的规则的关键帧选择器:由逗号分隔的 0% 到 100% 之间的百分比值列表,或者关键字 fromto,它们分别解析为 0% 和 100%。

指定关键帧选择器中值的数量和顺序必须与目标关键帧规则的值匹配。匹配对列表值周围的空格不敏感。

返回值

CSSKeyframeRule
找到的规则。

无异常

例如,给定以下动画
@keyframes colorful-diagonal-slide {

  from {
    left: 0;
    top: 0;
  }

  10% {
    background-color: blue;
  }

  10% {
    background-color: green;
  }

  25%, 75% {
    background-color: red;
  }

  100% {
    left: 100px;
    top: 100px;
  }

}

假设变量 anim 持有该动画的 CSSKeyframesRule 对象的引用,那么

anim.deleteRule('10%');
var tenPercent = anim.findRule('10%');

将首先删除最后的 10% 规则,即绿色背景颜色规则;然后找到剩余的蓝色背景规则并将其返回给 tenPercent

以下代码

var red = anim.findRule('75%');

将把 red 设置为 null。必须使用红色背景颜色规则的完整选择器来代替

var red = anim.findRule('25%,75%');

由于 from 映射到 0%,而 to 映射到 100%,我们可以使用任一值找到这些规则

var from = anim.findRule('0%'); // Returns from { left: 0; top: 0; } rule
var to = anim.findRule('to');   // Returns 100% { left: 100px; top: 100px; } rule

5.4. GlobalEventHandlers 接口混入的扩展

本规范扩展了 HTML 中的 GlobalEventHandlers 接口混入,以添加 事件处理器 IDL 属性,用于 动画事件,具体定义见 § 4.3 元素、Document 对象和 Window 对象上的事件处理器

5.4.1. IDL 定义

partial interface mixin GlobalEventHandlers {
  attribute EventHandler onanimationstart;
  attribute EventHandler onanimationiteration;
  attribute EventHandler onanimationend;
  attribute EventHandler onanimationcancel;
};

6. 隐私注意事项

本规范未收到任何隐私问题报告。

7. 安全注意事项

本规范未收到任何安全问题报告。

8. 更改记录

8.1. 2018 年 10 月 11 日工作草案以来的变更

进行了以下实质性变更

9. 致谢

特别感谢 Tab Atkins、Brian Birtles、Shane Stephens、Carine Bournez、Christian Budde、Anne van Kesteren、Øyvind Stenhaug、Estelle Weyl 以及所有其他 www-style 社区成员提供的反馈。

10. 其他待解决问题

需要指定关键帧如何交互

11. 等待编辑的工作组决议

本节为提示性内容且是临时的。

编辑人员目前在编辑本规范方面有所滞后。以下工作组决议仍需编辑加入

一致性

文档约定

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

本规范的所有文本均为规范性文本,明确标记为非规范性的部分、示例和注释除外。 [RFC2119]

本规范中的示例均以“例如”一词引入,或者通过 class="example" 与规范性文本隔开,如下所示

这是一个说明性示例。

说明性注释以“Note”一词开头,并使用 class="note" 与规范性文本隔开,如下所示

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

建议(Advisements)是规范性章节,旨在引起特别注意,并使用 <strong class="advisement"> 与其他规范性文本区分开来,如下所示: 用户代理必须提供可访问的替代方案。

一致性类别

本规范为三类一致性定义了一致性要求。

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

如果样式表包含的所有使用本模块定义语法的语句,根据通用 CSS 语法及本模块定义的各功能语法均有效,则该样式表符合本规范。

如果渲染器除了按相应规范解释样式表外,还通过正确解析本规范定义的所有功能并相应地渲染文档来支持这些功能,则该渲染器符合本规范。然而,由于设备限制导致 UA 无法正确渲染文档,并不意味着该 UA 不符合规范。(例如,UA 无需在单色显示器上渲染颜色。)

如果创作工具编写的样式表根据通用 CSS 语法及本模块中各功能的语法是句法正确的,并符合本模块中描述的所有其他样式表一致性要求,则该创作工具符合本规范。

部分实现

为了使作者能够利用前向兼容的解析规则来指定后备值,CSS 渲染器 **必须** 将其无法使用支持级别的任何 @规则、属性、属性值、关键字和其他语法结构视为无效(并 适当忽略)。特别地,用户代理 **不得** 在单一多值属性声明中选择性地忽略不支持的组件值而保留支持的值:如果任何值被视为无效(因为不支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有特性的实现

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

非实验性实现

一旦规范达到候选推荐阶段,非实验性实现即可成为可能,实现者应发布他们能够证明根据规范正确实现的任何 CR 级别特性的无前缀实现。

为建立并保持 CSS 在不同实现间的互操作性,CSS 工作组请求非实验性的 CSS 渲染器在发布任何 CSS 功能的无前缀实现之前,向 W3C 提交一份实现报告(并在必要时提交用于该实现报告的测试用例)。提交给 W3C 的测试用例需经 CSS 工作组审阅和修正。

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

索引

本规范定义的术语

通过引用定义的术语

引用

规范性引用

[CSS-DISPLAY-3]
Tab Atkins Jr.; Elika Etemad. CSS Display Module Level 3. 2022年11月18日. CR. URL: https://w3org.cn/TR/css-display-3/
[CSS-EASING-1]
Brian Birtles; Dean Jackson; Matt Rakow. CSS 缓动函数第 1 级. 2023 年 2 月 13 日. CR. URL: https://w3org.cn/TR/css-easing-1/
[CSS-SHAPES-2]
CSS Shapes Module Level 2 URL: https://drafts.csswg.org/css-shapes-2/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2021年12月24日. CR. URL: https://w3org.cn/TR/css-syntax-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 3 级. 2022年12月1日. CR. URL: https://w3org.cn/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 值与单位模块第 4 级. 2022年10月19日. WD. URL: https://w3org.cn/TR/css-values-4/
[CSS-WILL-CHANGE-1]
Tab Atkins Jr.. CSS Will Change Module Level 1. 2022年5月5日. CR. URL: https://w3org.cn/TR/css-will-change-1/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011年6月7日. REC. URL: https://w3org.cn/TR/CSS21/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification. 2016年4月12日. WD. URL: https://w3org.cn/TR/CSS22/
[CSS3CASCADE]
Elika Etemad; Tab Atkins Jr.. CSS 层叠和继承第 3 级. 2021 年 2 月 11 日. REC. URL: https://w3org.cn/TR/css-cascade-3/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021年8月26日. WD. URL: https://w3org.cn/TR/cssom-1/
[DOM]
Anne van Kesteren. DOM 标准. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.whatwg.cn/multipage/
[RFC2119]
S. Bradner. RFC 中用于指示要求级别的关键词. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WCAG20]
Ben Caldwell; et al. Web Content Accessibility Guidelines (WCAG) 2.0. 2008年12月11日. REC. URL: https://w3org.cn/TR/WCAG20/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/

参考资料

[CSS-BACKGROUNDS-3]
Bert Bos; Elika Etemad; Brad Kemper. CSS 背景和边框模块第 3 级. 2023 年 2 月 14 日. CR. URL: https://w3org.cn/TR/css-backgrounds-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS 定位布局模块第 3 级. 2023年2月17日. WD. URL: https://w3org.cn/TR/css-position-3/
[CSS3-TRANSITIONS]
David Baron; et al. CSS Transitions. 2018年10月11日. WD. URL: https://w3org.cn/TR/css-transitions-1/

属性索引

名称初始值应用于继承百分比动画类型 (Animation type)规范顺序计算值
animation <single-animation>#见各个属性所有元素不适用不可动画按语法见各个属性
animation-delay <time>#0s所有元素不适用不可动画按语法列表,每项是一个持续时间
animation-direction <single-animation-direction>#normal所有元素不适用不可动画按语法列表,每一项均为指定的关键字
animation-duration <time [0s,∞]>#0s所有元素不适用不可动画按语法列表,每项是一个持续时间
animation-fill-mode <single-animation-fill-mode>#none(无)所有元素不适用不可动画按语法列表,每一项均为指定的关键字
animation-iteration-count <single-animation-iteration-count>#1 所有元素不适用不可动画按语法列表,每一项要么是一个数字,要么是关键字 infinite
animation-name [ none | <keyframes-name> ]#none(无)所有元素不适用不可动画按语法列表,每一项是一个区分大小写的 css 标识符或关键字 none
animation-play-state <single-animation-play-state>#running所有元素不适用不可动画按语法列表,每一项均为指定的关键字
animation-timing-function <easing-function>#ease所有元素不适用不可动画按语法列表,每一项是一个计算出的 <easing-function>

IDL 索引

[Exposed=Window]
interface AnimationEvent : Event {
  constructor(CSSOMString type, optional AnimationEventInit animationEventInitDict = {});
  readonly attribute CSSOMString animationName;
  readonly attribute double elapsedTime;
  readonly attribute CSSOMString pseudoElement;
};
dictionary AnimationEventInit : EventInit {
  CSSOMString animationName = "";
  double elapsedTime = 0.0;
  CSSOMString pseudoElement = "";
};

partial interface CSSRule {
    const unsigned short KEYFRAMES_RULE = 7;
    const unsigned short KEYFRAME_RULE = 8;
};

[Exposed=Window]
interface CSSKeyframeRule : CSSRule {
  attribute CSSOMString keyText;
  [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
};

[Exposed=Window]
interface CSSKeyframesRule : CSSRule {
           attribute CSSOMString name;
  readonly attribute CSSRuleList cssRules;
  readonly attribute unsigned long length;

  getter CSSKeyframeRule (unsigned long index);
  undefined        appendRule(CSSOMString rule);
  undefined        deleteRule(CSSOMString select);
  CSSKeyframeRule? findRule(CSSOMString select);
};

partial interface mixin GlobalEventHandlers {
  attribute EventHandler onanimationstart;
  attribute EventHandler onanimationiteration;
  attribute EventHandler onanimationend;
  attribute EventHandler onanimationcancel;
};

问题索引

本规范需要定义如何从关键帧确定该值,就像关于 Transitions 应用 的章节对 CSS Transitions 所做的那样。
需要指定关键帧如何交互