直接用@keyframes+animation可实现可靠高性能滑入动画:定义slidein关键帧使元素从translatex(-20px)/opacity:0到translatex(0)/opacity:1,再通过animation:slidein 0.4s ease-out forwards应用,注意避免display:none、overflow:hidden等导致失效,并分离slide-in/slide-out逻辑确保多次进出稳定。

直接用 @keyframes + animation 就能实现可靠、高性能的滑入动画,不依赖 JavaScript,也不需要第三方库。
怎么定义 slideIn 关键帧
滑入动画本质是让元素从“不可见位置”移动到“目标位置”,同时配合透明度变化更自然。关键帧里必须用 transform(不是 left 或 margin),否则会触发重排、掉帧。
常见写法示例:
@keyframes slideIn {
from {
transform: translateX(-20px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
- 起始位移量(如
-20px)要根据容器宽度和设计预期调整,太大会导致动画过长,太小则看不出“滑”的感觉 - 必须同时设
opacity,否则元素会在位移前就突然出现 - 别写
0%/100%——from/to更简洁,语义也更清晰
怎么把动画加到元素上
光有关键帧没用,得用 animation 属性挂载。最易踩坑的是漏掉 forwards,导致动画一结束元素就“弹回原位”。
推荐写法:
.slide-in {
animation: slideIn 0.4s ease-out forwards;
}
-
0.4s是较稳妥的时长:短于 0.3s 显得太急,长于 0.6s 容易让人感知延迟 -
ease-out比linear更自然,收尾减速符合物理直觉 -
forwards必须加上,否则动画结束后transform和opacity会恢复初始值 - 不要在动画过程中再用 JS 改
style.transform,会覆盖 CSS 动画状态
为什么加了动画但没效果
常见失效原因不是代码写错,而是被其他样式或 DOM 状态干扰:
- 元素默认是
display: none?display: none下所有 CSS 动画都不触发,改用visibility: hidden+opacity: 0配合transform - 父容器设置了
overflow: hidden,但子元素滑入起点超出了裁剪区?检查translateX起始值是否被截断 - 动画类是通过 JS 动态添加的,但添加瞬间浏览器还没完成样式计算?加个
setTimeout(() => el.classList.add('slide-in'), 0)强制进下一帧 - 用了
will-change: transform却没配transform: translateZ(0)?某些旧版 Safari 会因此禁用 GPU 加速
滑入后还想支持退出动画怎么办
别在一个 class 里反复 toggle 同一个动画,容易状态混乱。正确做法是分离进入/退出逻辑:
.slide-in { animation: slideIn 0.4s ease-out forwards; }
.slide-out { animation: slideOut 0.35s ease-in forwards; }
@keyframes slideOut {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(20px); opacity: 0; }
}
- 退出动画时长建议略短于进入(如
0.35svs0.4s),避免视觉拖沓 - 监听
animationend事件,在slide-out结束后真正移除元素或重置状态,而不是靠定时器猜时间点 - 如果元素需多次进出,每次切换前先
el.classList.remove('slide-in', 'slide-out'),再按需添加,防止 class 冲突
真正难的不是写出第一版滑入动画,而是在不同设备、不同加载时机、不同 DOM 插入方式下保持行为一致。尤其是 SPA 动态渲染或 SSR 后 hydrate 的场景,animation 触发时机比你想象中更敏感。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











