核心是用状态类名(如.page-enter-active/.page-leave-active)控制动画触发,配合animation-fill-mode: both、仅用opacity/transform等高性能属性,并严格管理类名增删时机与层叠上下文。

怎么用 animation 实现页面切换动画
核心是「状态类名控制动画触发」,不是靠 JS 直接调用 animate() 或操作 keyframes。浏览器对 class 切换的重绘更可控,也更容易和路由、组件生命周期对齐。
常见错误是把动画写在初始样式里(比如直接给 .page 加 animation),结果一进页面就播,无法响应「进入/离开」两个方向。
- 动画必须绑定在「带状态语义的类名」上,比如
.page-enter-active、.page-leave-active - 进入和离开需分离定义:进入时加
.page-enter→.page-enter-active,离开时加.page-leave→.page-leave-active - 务必设置
animation-fill-mode: both,否则动画结束瞬间样式会回退到初始值(比如 opacity 突然变 1)
@keyframes 里不要写 layout 触发属性
像 height、top、left 这类会触发 Layout 的属性,在动画中会导致卡顿,尤其在低端设备或复杂 DOM 下。
优先用只触发 Composite 的属性:opacity、transform(translateX、scale、rotate)。
立即学习“前端免费学习笔记(深入)”;
@keyframes slideInRight {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.page-enter-active {
animation: slideInRight 0.3s ease-out;
animation-fill-mode: both;
}
如何避免多个页面同时动画打架
当路由快速切换(比如连点两次导航),旧页面还没走完 leave 动画,新页面就进来了,容易出现层叠、错位、z-index 混乱。
- 给容器加
position: relative和统一z-index,再用transform: translateZ(0)强制生成新层叠上下文 - 离开动画结束后,JS 必须手动移除
.page-leave-active类(CSS 不会自动清理) - 进入动画开始前,确保旧页面已移除
.page-enter-active,可用getComputedStyle(el).animationName检查是否还在播
React/Vue 中 class 切换时机很关键
不能等组件 mounted 或 useEffect 才加类 —— 那时 DOM 已渲染完毕,动画会漏掉第一帧。
正确做法是在「决定切换」的瞬间(如点击导航后、路由解析完成时)立刻添加 enter/leave 类,再让框架更新 DOM。
- Vue:用
的enter-from-class/leave-to-class配合appear,别手写 class 切换逻辑 - React:用
useLayoutEffect在 DOM 绘制前加类,比useEffect更稳 - 纯 HTML + JS:监听
popstate后立即操作 class,然后用requestAnimationFrame延迟一帧再更新内容










