SCSS 顶层不能用 @for 或 @each 直接生成 @keyframes,因 CSS 标准要求关键帧名必须是静态字符串;唯一安全方式是将循环封装进 @mixin 后显式 @include 调用。

不能在 SCSS 顶层用 @for 或 @each 直接生成 @keyframes,否则编译报错;必须把循环逻辑收进 @mixin,再显式 @include 调用——这是唯一能安全生成多个关键帧且名称可控的方式。
为什么顶层 @keyframes + 循环会报错
SCSS 编译器要求 @keyframes 名称必须是静态字符串,不接受变量插值。比如下面这段:
@for $i from 1 through 3 {
@keyframes slide-#{$i} {
0% { transform: translateX(-#{$i * 100px}); }
100% { transform: translateX(0); }
}
}
会直接报错:Invalid CSS after "@keyframes slide": expected identifier, was "#{$i}"。根本原因不是 SCSS 不够强,而是 CSS 标准本身禁止运行时关键帧名——浏览器无法预加载、无法 GPU 加速,甚至可能触发重排。
@mixin 是唯一安全的封装入口
只有在 @mixin 内部,#{$var} 插值才被允许用于 @keyframes 名,并且每次 @include 都会生成独立、静态的关键帧规则。
- 名称必须带项目前缀(如
my-slide-in),避免和第三方库冲突 - 不要拼接参数进名称(如
slide-in-0.4s-ease-out),CI 检查会崩溃,也破坏可维护性 - 每个
@mixin应只定义一组语义化关键帧,例如@mixin fade-in-keyframes对应@keyframes my-fade-in - 调用时传参控制行为(
$duration,$easing),但不改变关键帧名
关键帧内容必须只用 transform 和 opacity
这两类属性走合成层,不触发重排重绘。一旦混入 left、top、width 或 background-position(除非配合 will-change 显式声明),动画就容易卡顿。
- 骨架屏扫光动画若用
background-position,得提前用 SCSS 函数封装偏移范围,例如skeleton-shine-offset($range) - IE11 降级 fallback 不能靠循环自动生成,得手动补
opacity替代方案 - 多段关键帧(如 0% → 60% → 100%)别用循环生成帧,顺序不可控,改用手动写
@content的模板 mixin
真正复用的关键帧库结构
分离定义与调用:统一在 _animations.scss 中用 @use 引入,而非 @import。
-
@keyframes全部静态命名、带前缀、只含transform/opacity - 每个关键帧配一个同名
@mixin(如@mixin fade-in),只封装animation属性参数 - 关键帧内部数值全由 SCSS 变量驱动(如
$anim-fade-duration: 0.3s),方便全局调整 - 禁用
@mixin anim($value) { animation: $value; }这种偷懒写法——它切断了对关键帧逻辑的控制权
最容易被忽略的是:所有 @keyframes 都挂载在全局 CSSOM,Sass 不做去重,哪怕你 @include 同一个 mixin 十次,也会输出十份重复规则。所以关键帧命名必须语义清晰、项目独占,不能指望“作用域隔离”。


















