大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。
动画是体验的核心,比如引导用户从一次交互到下一次交互, 但网页的流畅动画还存在一些不足,其中包括设置进入和退出动画的能力,以及为对话框和弹出窗口等可关闭元素平滑往返顶层的动画效果。
为了填补这些空白,Chrome 116 和 117 包含了四个新的 Web 平台功能,可实现离散属性的平滑动画和过渡。这四项新功能包括:
从 Chrome 116 开始,可以在关键帧规则中使用 display 和 content-visibility。然后,它们将在关键帧出现时交换,不需要其他额外配置:
.card { animation: fade-out 0.5s forwards;}@keyframes fade-out { 100% { opacity: 0; display: none; }}
上面的示例在 0.5 秒的时间内将 opacity 设置为 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。
allow-discrete 模式让离散动画成为可能,可以将其作为 transition-behavior 的值,transition-behavior接受 normal 或者 allow-discrete 两个属性。
.card { transition: opacity 0.25s, display 0.25s; transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */}.card.fade-out { opacity: 0; display: none;}
transition 简写也是一样,可以省略该属性并在每个 transition 的末尾使用 allowed-discrete 关键字。
.card { transition: opacity 0.5s, display 0.5s allow-discrete;}.card.fade-out { opacity: 0; display: none;}
如果要对多个离散属性进行动画处理,则需要在要对其进行动画处理的每个属性后面包含allow-discrete。例如:
.card { transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;}.card.fade-out { opacity: 0; display: none;}
到目前为止,本文已经介绍了退出动画,要创建进入动画,需要使用 @starting-style 规则。使用 @starting-style 应用浏览器在页面上打开元素之前可以查找的样式, 这是“before-open”状态。
/* 0. BEFORE-OPEN STATE *//* Starting point for the transition */@starting-style { .item { opacity: 0; height: 0; }}/* 1. 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;}/* 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);}
要将元素动画化到顶层或从顶层动画化,请在“打开”状态下指定@starting-style,以告诉浏览器从何处开始动画化。 对于对话框,打开状态由 [open] 属性定义, 对于弹出窗口,请使用 :popover-open 伪类。
一个简单的对话框示例如下所示:
/* 0. BEFORE-OPEN STATE */@starting-style { dialog[open] { translate: 0 100vh; }}/* 1. IS-OPEN STATE */dialog[open] { translate: 0 0;}/* 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. 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; } /* 1. IS-OPEN STATE */ /* state when popover is open, BOTH: what we're transitioning *in* to and transitioning *out* from */ transform: translateY(0); opacity: 1; } /* 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 将跳过剪辑和变换,并将内容放在顶层。
如果不过渡叠加,元素将立即返回到被剪切、变换和覆盖的状态,并且看不到过渡发生。
[open] { transition: opacity 1s, display 1s allow-discrete;}
相反,应在transition 和 animation中包含overlay,以便将叠加层与其余功能一起进行动画处理,并确保在制作动画时其保留在顶层,这看起来会平滑得多。
[open] { transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;}
如果要更改 DOM,例如在 DOM 中添加和删除元素,平滑动画的另一个很好的解决方案是视图转换,以下是使用视图转换构建的上述示例中的两个。
在第一个演示中,视图过渡将处理过渡,而不是设置 @starting-style 和其他 CSS 转换。 视图转换设置如下:
首先,在 CSS 中,为每张卡指定一个单独的视图转换名称。
.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(); }})
https://developer.chrome.com/blog/entry-exit-animations/
https://www.youtube.com/watch?app=desktop&v=lsYlEzuXq-w