不能用 @include 动态生成 @keyframes 名,因会导致命名冲突、ci 检查失效和 gpu 加速失效;应使用固定带前缀的 keyframes 名(如 my-bounce-in),@mixin 仅封装调用逻辑。

为什么不能用 @include 动态生成 @keyframes 名
SCSS 编译后,所有 @keyframes 都挂载在 CSS 全局作用域,不存在“模块级作用域”。用 @include bounce-animation($duration, $easing) 拼出 @keyframes bounce-#{$duration}-#{$easing},看似灵活,实则埋下三颗雷:命名冲突(多个组件同时引入会覆盖)、CI 检查失效(grep 找不到固定名)、GPU 加速失效(浏览器无法预判“伪动态”关键帧)。真正可维护的做法是:每个物理回弹动画对应一个**固定、带项目前缀的 @keyframes 名**,比如 @keyframes my-bounce-in 或 @keyframes my-bounce-back。
@mixin 只封装调用逻辑,不碰关键帧定义
关键帧内容必须稳定,@mixin 仅控制时长、缓动、填充模式等运行时行为。例如:
@mixin bounce-in($duration: 0.6s, $easing: cubic-bezier(0.17, 0.67, 0.83, 0.67), $fill: forwards) {
animation: my-bounce-in $duration $easing $fill;
}
-
$easing必须默认设为cubic-bezier(0.17, 0.67, 0.83, 0.67)—— 这是 macOS 级 spring 曲线,比cubic-bezier(0.34, 1.56, 0.64, 1)更稳,兼容性更好(Chrome 43+/Firefox 16+/Safari 9+) - 不要把整条
animation值当参数传,比如写@mixin anim($value) { animation: $value; },这会让后续微调起始缩放值或加transform-origin变得极其困难 - 若需不同幅度的回弹(如按钮轻弹 vs 卡片重落),应定义多个独立关键帧(
my-bounce-in-light/my-bounce-in-heavy),而非靠 mixin 参数硬塞进同一套帧
关键帧内部只用 transform 和 opacity
物理回弹感来自弹性缓动 + 高频合成属性,不是靠 JS 模拟弹簧。所以 @keyframes my-bounce-in 必须满足:
- 只操作
transform: translateY()、scale()、rotate(),绝不用top、left、width、height—— 否则触发 layout,动画卡顿 - 若需淡入配合,用
opacity,别用visibility或display,后者无法动画 - 手动设置中间关键帧增强物理感:比如
60% { transform: translateY(-15px) scale(1.1); },比单纯靠贝塞尔曲线更可控 - 加
will-change: transform;在触发前声明,提示浏览器提前升层
JS 触发回弹时,必须清理内联样式干扰
比如拖动结束后要执行 bounce-back 动画,但元素当前已有 style.transform = 'translateX(82px)',此时直接加 class 不生效——内联样式优先级高于 class 中的 transform。正确做法是:
- JS 中先清空内联
transform:el.style.transform = '' - 再通过
el.style.setProperty('--bounce-target', '82px')把目标值传给 CSS 自定义属性 - CSS 中用
@keyframes读取该变量:transform: translateX(calc(var(--bounce-target) * -1));(需搭配calc()和合理初始值) - 或更稳妥:JS 设置
el.classList.add('bounce-back')的同时,用el.style.removeProperty('transform')清除干扰
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











