动效是任何数字体验的核心部分,可引导用户从一次互动过渡到下一次互动。但在 Web 平台上,流畅的动画存在一些间隔。这些功能包括能够轻松为进入和退出动画添加动画效果,以及为对话框和弹出式窗口等可关闭元素在顶层之间平滑地添加动画效果。
为了填补这些空白,Chrome 116 和 117 中包含四项新的 Web 平台功能,可为离散属性实现流畅的动画和转场效果。
这四项新功能包括:
- 能够在关键帧时间轴上为
display
和content-visibility
添加动画效果(从 Chrome 116 开始)。 - 使用
allow-discrete
关键字的transition-behavior
属性,以启用display
等离散属性的转换(从 Chrome 117 开始)。 - 用于为从
display: none
进入顶层的进入效果添加动画的@starting-style
规则(从 Chrome 117 开始)。 overlay
属性,用于控制动画期间顶层的行为(从 Chrome 117 开始)。
在关键帧中显示动画
从 Chrome 116 开始,您可以在关键帧规则中使用 display
和 content-visibility
。然后,这些元素会在关键帧出现时进行切换。无需任何其他新值即可支持此功能:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
上述示例会在 0.5 秒的时间内将不透明度动画化为 0,然后将“display”设置为“none”。此外,forwards
关键字可确保动画保持其结束状态,以便应用于它的元素保持 display: none
和 opacity: 0
。
下面是一个简单的示例,模拟了您可以使用转场效果执行的操作(请参阅“转场”部分中的演示)。不过,转场效果无法制作更复杂的动画,例如以下示例:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
spin-and-delete
动画是退出动画。首先,卡片将沿着 y 轴旋转,并进行色相旋转,然后在时间轴上的 80%
处,将其不透明度从 1 过渡到 0。最后,卡片从 display: block
切换为 display: none
。
对于这些退出动画,您可以为其设置触发器,而不是直接将其应用于元素。例如,将事件监听器附加到触发某个类应用动画的按钮,如下所示:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
上面的示例现在的结束状态为 display:none
。在许多情况下,您需要进一步移除 DOM 节点,并设置超时,以便动画先完成。
转换离散属性
默认情况下,以离散方式进行动画处理的属性不会触发转场事件。如需启用此功能,请将转换行为模式设置为 allow-discrete
。
transition-behavior
属性
transition-behavior
属性用于指定是否为离散属性启动转换。它接受两个值:normal
和 allow-discrete
,初始值为 normal
。
normal
:系统不会针对离散属性启动转换,只会针对可插值属性启动转换。allow-discrete
:系统将为离散属性和可插值属性启动转换。
如需为特定媒体资源启用 allow-discrete
模式,请将其添加到 transition
缩写中:
.card {
transition: opacity 0.25s, display 0.25s allow-discrete; /* Enable allow-discrete for the display property */
}
.card.fade-out {
opacity: 0;
display: none;
}
在转换多个离散属性时,您必须为每个转换属性设置 allow-discrete
。例如:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
或者,如需为所有过渡属性设置行为,请在 transition
声明后声明 transition-behavior: allow-discrete
。这通常是最简单的方法。
.card {
transition: opacity 0.5s, display 0.5s, overlay 0.5s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
用于条目动画的 @starting-style
规则
到目前为止,本文已介绍了退出动画,如需创建进入动画,您需要使用 @starting-style
规则。
使用 @starting-style
应用一种样式,以便浏览器在网页上打开元素之前查找该样式。这是“打开前”状态(动画从此处开始)。
/* 0. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 1. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
现在,您已为这些待办事项列表项提供了进入和退出状态:
为元素添加从顶层进入和离开的动画效果
如需为元素添加从顶层进入和离开的动画效果,请在“open”状态下指定 @starting-style
,以告知浏览器从哪里进入动画效果。对于对话框,使用 [open]
属性定义打开状态。对于弹出式窗口,请使用 :popover-open
伪类。
对话框的简单示例如下所示:
/* 0. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 1. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
在下一个示例中,进入和退出效果不同。从视口底部向上动画进入,从视口顶部动画退出。它还使用嵌套 CSS 编写,以实现更好的视觉封装。
为弹出式窗口添加动画时,请使用 :popover-open
伪类,而不是之前使用的 open
属性。
.settings-popover {
&:popover-open {
/* 0. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
/* 1. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
overlay
个房源
最后,如需使顶层的 popover
或 dialog
淡出,请将 overlay
属性添加到转场列表中。popover
和 dialog
会转义祖先剪辑和转换,还会将内容放置在顶层。如果您不对 overlay
进行转换,元素将立即恢复剪裁、转换和遮盖状态,并且您不会看到转换过程。
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
而是在过渡或动画中添加 overlay
,以便将 overlay
与其余功能一起添加到动画中,并确保它在动画播放时保持在顶层。这样看起来会更流畅。
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
此外,当您在顶层打开多个元素时,叠加层有助于您控制进入和退出顶层的流畅过渡。您可以在这个简单的示例中了解其中的区别。如果您在第二个弹出式窗口过渡时不向其应用 overlay
,则它会先移出顶层,跳到另一个弹出式窗口后面,然后再开始过渡。这种效果不太流畅。
关于视图转换的注意事项
如果您要进行 DOM 更改(例如在 DOM 中添加和移除元素),视图转换是实现流畅动画的另一个绝佳解决方案。下面是上述两个使用视图转换构建的示例。
在此第一个演示中,视图转场将处理转场,而不会设置 @starting-style
和其他 CSS 转换。视图转换的设置如下所示:
首先,在 CSS 中,为每张卡片分配一个单独的 view-transition-name
。
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
然后,在 JavaScript 中,将 DOM 更改(在本例中为移除卡片)封装在视图转换中。
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
现在,浏览器可以处理每个卡片淡出并变形到新位置。
另一个适合使用此方法的示例是“添加/移除列表项”演示。在这种情况下,您需要记得为创建的每张卡添加唯一的 view-transition-name
。
总结
这些新的平台功能让我们离在 Web 平台上实现流畅的进入和退出动画又近了一步。如需了解详情,请访问以下链接: