@keyframes必须位于less文件顶层,不可嵌套在选择器或mixin中;正确写法为全局静态声明,动态命名需用~"@{name}"转义;动画属性应拆分为独立mixin以提升可维护性与兼容性。

Less里写@keyframes必须放在顶层,嵌套就编译失败
很多人把@keyframes塞进选择器或.mixin()里,结果编译输出为空、报ParseError: Unexpected token,甚至没任何提示。这不是Less“不支持”,而是它把@keyframes当作顶层指令处理——就像@import或@media一样,不能出现在任何{}块内部。
常见错误写法:
-
.btn { @keyframes hover-bounce { ... } }→ 编译失败 -
.animate(@name) { @keyframes @{name} { ... } }→ 变量不解析,或直接报错
✅ 正确做法:所有@keyframes声明必须在文件最外层(即不在任何选择器、mixin、媒体查询内),且名称是静态字符串:
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
IE11 兼容注意:from/to不被识别,必须写成0%/100%。
想动态生成动画名?用~"@{name}"转义,但名字仍得全局唯一
Less 不允许@keyframes @{prefix}-slide这种纯变量插值,但可以用字符串拼接+转义实现近似效果。关键点不是“动态命名”,而是确保最终输出的 CSS 名字合法、不冲突。
操作要点:
- 在文件顶部统一定义前缀变量:
@prefix: card; - 声明时用
~"@{prefix}-slide",调用时也用完全相同的表达式:animation: ~"@{prefix}-slide" 0.3s; - 避免前缀含空格、斜杠、括号等非法字符;大小写敏感,
CardSlide和cardslide算两个不同动画 - 多文件共用时,把所有
@keyframes集中到animations/_keyframes.less,用@import (once)引入
.animate-time()这类mixin别堆参数,拆开才好覆盖
把animation-name、duration、fill-mode全塞进一个.animate(@name, @dur, @easing, @count)里,极易传参错序,后期改个时长还得重写整行。更糟的是,漏掉animation-fill-mode: forwards会导致动画一结束就回退到初始态——而animation简写属性默认不包含它。
推荐拆成独立 mixin:
.animate-name(@name) { animation-name: @name; }.animate-time(@dur: 0.3s) { animation-duration: @dur; }.animate-fill(@mode: forwards) { animation-fill-mode: @mode; }
单位要统一:全用s或全用ms,300ms和0.3s混用可能引发浏览器解析差异。
多个动画叠加别靠 mixin 嵌套,用 class 组合更可控
写.animate-scale().animate-glow().animate-border()看似方便,实际是文本替换,最终会因 CSS 声明顺序导致后写的animation-name覆盖前面的。浏览器不认“叠加”,只按最后生效的animation值执行。
可行方案:
- 定义语义化 class:
.is-scaling、.has-glow、.border-pulsing,各自绑定不同@keyframes - HTML 中多 class 控制:
<button class="is-scaling has-glow"></button> - 若必须逗号写法:
animation: scale-in 0.3s, glow 1s;,注意旧版 Safari 对多动画支持不稳定,生产环境建议 JS 动态切换 class
响应式节奏调整只能靠媒体查询包裹 mixin 调用,不能在 mixin 内部写 when (@screen = mobile) —— Less 没有运行时条件判断能力,所有逻辑都在编译期展开。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











