Less中不能直接用变量名定义@keyframes名称,因编译器将其视为纯CSS文本,不支持插值;唯一合法方式是Less 4.0+中用.each()循环配合#{}插值生成。

Less里不能直接用变量名定义@keyframes名称
Less编译器在解析@keyframes时,会把整个规则块当作纯CSS文本处理,不支持在@keyframes后直接插值(比如@keyframes @name)。哪怕你写了@name: fade-in;,@keyframes @name也会被原样输出,浏览器无法识别——它看到的是@keyframes @name,而不是@keyframes fade-in。
常见错误现象:Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet' 或动画完全不触发,DevTools里查不到对应@keyframes规则。
- Less 3.12+ 支持
%占位符 +.rule()混合,但@keyframes本身不接受选择器语法,这条路走不通 - 不能靠
~"@{name}"拼接——@keyframes ~"@{name}"语法非法,编译直接报错 - 唯一合法且稳定的方式:用
.each()循环 +#{}插值(仅Less 4.0+)或退而求其次,用字符串拼接生成完整规则块
Less 4.0+ 中用.each()和#{}安全生成多组关键帧
Less 4.0 引入了#{}插值语法,允许在规则名、选择器、甚至@keyframes名称中动态注入变量值。配合.each()可批量生成不同名称的关键帧动画。
.animations(@list) when (islist(@list)) {
.each(@list, {
@name: e(@value[0]);
@from: e(@value[1]);
@to: e(@value[2]);
@keyframes @{name} {
from { opacity: @from; }
to { opacity: @to; }
}
});
}
// 调用
.animations([
["fade-in", 0, 1],
["fade-out", 1, 0],
["slide-up", 0.5, 1]
]);
注意:e()用于解包字符串(避免引号残留),@{name}必须写在@keyframes后紧邻位置,不能有空格或换行干扰;若变量含连字符(如"fade-in"),e()能确保它不被当成减法运算。
立即学习“前端免费学习笔记(深入)”;
兼容旧版Less(~""包裹整个@keyframes块
Less 3.x 不支持@{name}在@keyframes后插值,但允许用~""将整段CSS当字符串输出。缺点是失去语法高亮和嵌套能力,但能跑通。
.make-keyframe(@name, @from, @to) {
@block: ~"@keyframes @{name} { from { opacity: @{from}; } to { opacity: @{to}; } }";
@{block};
}
.make-keyframe(fade-in, 0, 1);
.make-keyframe(slide-left, 1, 0);
这种写法本质是字符串拼接,所以:
-
@name必须是纯字符串(不能是数字或带运算的表达式) - 所有CSS属性值都要手动转义,比如
transform: translateX(@{x})得写成~"transform: translateX(@{x})" - 无法做条件判断(比如
if (@duration > 1s)),逻辑要提前在JS层或调用侧处理
变量命名与维护成本:别为了“复用”牺牲可读性
很多人想用变量统一管理动画名、持续时间、缓动函数,结果写出一堆@anim-fade-name、@anim-fade-duration、@anim-fade-timing……最后改一个动画要翻五处。
更实际的做法:
- 只对真正高频变化的值抽变量,比如
@duration-base: 0.3s;,然后animation: fade-in @duration-base ease-out; -
@keyframes名称保持语义化固定(fade-in,rotate-360),不要试图用@anim-type动态生成 - 复杂动画建议拆成独立
.less文件(如animations/fade.less),用@import按需引入,比变量拼接更易定位和协作
最常被忽略的一点:浏览器对@keyframes名称大小写敏感,@keyframes FadeIn和@keyframes fadeIn是两个动画——而Less变量不区分大小写,@name: "FadeIn";和@name: "fadeIn";在插值后可能意外覆盖,调试时容易卡住。


















