不能直接在scss顶层用@for生成@keyframes,因css标准要求关键帧名必须是静态字符串,而scss仅允许在@mixin内通过#{}插值动态生成名称,否则编译报错。

为什么不能直接在SCSS顶层用 @for 生成 @keyframes
编译会报错:Invalid CSS after "@keyframes slide": expected identifier, was "#{$i}"。根本原因是 CSS 标准要求关键帧名称必须是静态字符串,而 SCSS 在顶层不支持对 @keyframes 名称做变量插值。即使你写 @for $i from 1 through 3 { @keyframes shine-#{$i} { ... } },SCSS 编译器也会拒绝——它只允许在 @mixin 内部通过 #{} 动态生成名称。
必须用 @mixin 封装循环逻辑并显式调用
把 @for 或 @each 放进 @mixin 里,再用 @include 调用,才能让每个动画获得唯一、可预测的名称和行为。例如:
@mixin generate-skeleton-shine($speeds: (slow: 2.5s, medium: 1.8s, fast: 1.2s)) {
@each $name, $duration in $speeds {
@keyframes skeleton-shine-#{$name} {
0% {
background-position: -200% 50%;
}
100% {
background-position: 200% 50%;
}
}
}
}
@include generate-skeleton-shine;
-
$speeds是一个 map,语义清晰,便于维护和扩展 - 生成的动画名如
skeleton-shine-slow,不会冲突,也方便 JS 或 class 控制 - 关键帧内所有值都展开为静态数值(如
-200%),不依赖运行时计算 - 必须显式
@include,否则 mixin 不生效;只声明不调用等于没写
生成的 keyframes 必须只用 transform 和 opacity,且避免 calc()
骨架屏动画本质是 background-position 位移,但它不属于合成属性,所以要格外注意性能边界:浏览器对 background-position 动画的支持虽好,但若混入 calc() 或嵌套变量,某些旧版 Chrome 会降级到主线程渲染,导致卡顿。正确做法是:
- 所有位移值写死或用 SCSS 变量 +
#{}插值,例如background-position: -#{$offset} 50% - 不使用
calc(100% - 20px)这类表达式——它在@keyframes中不可靠,尤其在 iOS Safari 上常被忽略 - 动画时长、缓动函数等应作为 mixin 参数传入,而非硬编码,方便后续统一调整
- 如果需兼容 IE11,不能只靠循环生成 fallback;得额外加
opacity方案,并手动控制显隐逻辑
错峰动画要用 nth-child + animation-delay,别指望 JS 控制节奏
真实加载是逐行出现的,骨架屏若全部同步闪,反而暴露“假感”。SCSS 可在生成类时一并注入延迟,例如:
.skeleton-item {
@for $i from 1 through 6 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.08}s;
}
}
}
这样编译后就是 6 个独立选择器,每个带不同 animation-delay。注意:
- 延迟值必须是静态数字(如
0.08s),不能写成#{$i} * 0.08s—— SCSS 不支持单位参与运算 - 延迟不宜超过 0.5s,否则首屏感知变慢;建议控制在 0.05–0.12s 区间
- 不要给父容器设 delay 后让子元素继承——
animation-delay不继承,必须写在具体元素上
真正麻烦的是动画与内容生命周期的耦合:CSS 只管“怎么闪”,但“什么时候停”得靠 JS 切换 visibility 或 display,且必须在数据就绪瞬间执行,差一帧都会闪或跳。这个衔接点,SCSS 帮不上忙。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











