如何在LESS中设置关键帧名称

28

我尝试设置这个LESS mixin,用于CSS动画的关键帧:

.keyframes(@name, @from, @to) {;
  @-webkit-keyframes "@name" {
    from {
      @from;  
    }
    to {
      @to;
    }
  }
}

但是名称短语存在问题,是否有任何选项可以正确解决这个问题?


可能是@ sign and variables in CSS keyframes using LESS CSS的重复问题 - 尽管这里最高票答案目前比其他问题中的顶级答案更为更新。 - Jari Keinänen
尝试这段代码 https://css-tricks.com/forums/topic/keyframes-is-not-working-in-less-mixin-with-lesshat/ - Haydar C.
两年后,谢谢 :) - Lukas
6个回答

32

从 LESS 1.7 开始,您可以使用变量作为关键帧 (names) 的关键字。

LESS 1.7 对指令的处理方式进行了一些更改,允许在 @keyframes 的名称/关键字中使用变量(所以问题中的示例现在应该可行)。


不幸的是,在 LESS <= 1.6 中无法动态生成关键帧名称。

因此,关键帧的常规方法将使用硬编码的名称,并且您只会调用特定的“for”和“to” mixin,如下所示:

.colors-mixin-frame(@from,@to){
from {color: @from;}
to {color: @to;}
}

.width-mixin-frame(@from,@to){
from {width: @from;}
to {width: @to;}
}

// keyframes with hardcoded names calling for specific mixin frames
@keyframes red-blue { .colors-mixin-frame(red, blue); }
@keyframes change-width { .width-mixin-frame(254px, 512px); }

但是你可以使用一种变通方法动态生成名称

在规则名称中注入名称,但这需要一个提供关键帧声明末尾的闭括号}的下一个规则的声明。最方便的方法是只需调用该关键帧构建动画即可。


.animation-keyframes(@name, @from, @to, @anim-selector) {
  @keyf: ~"@keyframes @{name} { `'\n'`from ";
  @anim: ~"} `'\n'`.@{anim-selector}";
  @{keyf} {
      .from(@name,@from);
        }
      to {
        .to(@name,@to);
      }
  @{anim} {
    animation-name:@name;
  }
}

请注意,您还需要定义.from(){}.to(){}混合器,而不仅仅像您在示例中所做的那样使用@from@to(因为LESS也不允许动态生成属性)...这些混合器现在可以构建所需的属性和值。要使用特定属性,您可以使用保护或名称特定的混合器,例如:

// name-specific from and to mixins that are used if first argument equals "colors"
.from (colors, @color) {
  color: @color;
}
.to (colors, @color) {
  color: @color;
} 

现在我们可以在LESS中调用我们的混合器:

// test
.animation-keyframes (colors, red, blue, my-colanim);

并获得 CSS:

@keyframes colors { 
from {
  color: #ff0000;
}
to {
  color: #0000ff;
}
} 
.my-colanim {
  animation-name: colors;
}

这也适用于LESS 1.4,但请注意我们使用了JavaScript插值来进行换行,这需要一个JavaScript实现的LESS。


编辑:关于前缀的额外问题

带有供应商前缀的Mixin

在这里,我创建了两个mixin...一个没有供应商前缀,另一个有供应商前缀,两者都调用了一个通用的.keyframes mixin:

.keyframes (@name, @from, @to, @vendor:"", @bind:"") {
  @keyf: ~"@{bind}@@{vendor}keyframes @{name} { `'\n'`from ";
  @{keyf} {
      .from(@name,@from);
        }
      to {
        .to(@name,@to);
      }
}

.animation-keyframes-novendor (@name, @from, @to, @anim-selector) {
  .keyframes (@name, @from, @to);
  @anim: ~"} `'\n'`.@{anim-selector}";
  @{anim} {
    animation-name:@name;
  }
}

.animation-keyframes (@name, @from, @to, @anim-selector) {
  @bind: "} `'\n'`";
  .keyframes (@name, @from, @to, "-moz-");
  .keyframes (@name, @from, @to, "-webkit-", @bind);
  .keyframes (@name, @from, @to, "-o-", @bind);
  .keyframes (@name, @from, @to, "-ms-", @bind);
  .keyframes (@name, @from, @to, "", @bind);
  @anim: ~"} `'\n'`.@{anim-selector}";
  @{anim} {
    -moz-animation: @name;
    -webkit-animation: @name;
    -o-animation: @name;
    -ms-animation: @name;
    animation: @name;
  }
}

.from (colors, @color) {
  color: @color;
}
.to (colors, @color) {
  color: @color;
}

/* keyframes with all vendor prefixes */
.animation-keyframes (colors, red, blue, my-colanim);

/* keyframes with no vendor prefix */
.animation-keyframes-novendor (colors, red, blue, my-colanim);

.animation-keyframes将为所有供应商前缀生成关键帧和具有供应商前缀属性的动画选择器。而.animation-keyframes-novendor与上述简单解决方案(没有供应商前缀)产生相同的输出。


一些注意事项:

  • 要使您的动画实际工作,您需要设置其他动画参数,例如timing-function、duration、direction、iteration-count(除了我们已经设置的名称之外,至少需要一个持续时间)。

    例如:

   animation: @name ease-in-out 2s infinite alternate;
  • 如果您将上述mixin放入命名空间中,请确保将其他mixin内的mixin引用更改为它们的完整路径(包括命名空间)。

    例如:

   #namespace > .keyframes () // see .less source in the demo for details

1
@djlukas777,我在答案中添加了一个带有供应商前缀的mixin的扩展版本。 - Martin Turjak
@chandlervdw 你好!在上面的示例中,我关注了 LESS 部分 - 通过动态分配名称来获取所需的 CSS 输出。CSS 只有动画名称,您应该根据自己的需要进行调整(CSS 中的工作动画至少需要持续时间)。实际上,您应该添加一些动画参数,例如 timing-function、duration、direction、iteration-count。这里是一个jsfiddle中的可用示例。 - Martin Turjak
1
这个解决方案对我很有效。我无法在命名空间内使用这个mixin。所以,如果你将mixin放在#animation命名空间中,并使用#animation > .animation-keyframes(...)调用它,你会收到一个消息说mixin未定义。有人知道如何在仍然从命名空间内工作的情况下解决这个问题吗? - user1429980
1
@user1429980 如果您将上述mixin包装在命名空间中,它应该可以工作,您只需要确保使用其完整路径(包括命名空间,例如在.animation-keyframes(...) mixin内部使用#animation > .keyframes(...))。演示 - Martin Turjak
1
@Danield 如果你想要重复使用相同的 .from.to mixins,你需要在 .keyframes mixin 中硬编码它(或者添加另一个参数,这取决于你想要做什么),因为具有不同属性的生成的关键帧现在需要不同的名称(例如:color-change2,但是你想要使用的步骤应该保持 color-change)... 在这里,我使用更新的 .keyframes mixin 分叉了你的笔记本电脑: codepen example - Martin Turjak
显示剩余11条评论

6

我目前正在开发一个混合库。

源代码可以在这里找到:https://github.com/pixelass/more-or-less

我的关键帧混合器如下:

适用于LESS 1.7.x

混合器

.keyframes(@name) { 
    @-webkit-keyframes @name {
        .-frames(-webkit-);
    }
    @-moz-keyframes @name {
        .-frames(-moz-);
    }
    @keyframes @name {
        .-frames();
    }
}

输入

& {
    .keyframes(testanimation);.-frames(@-...){
        0% {
            left: 0;
            @{-}transform: translate(10px, 20px);
        }

        100% {
            left: 100%;
            @{-}transform: translate(100px, 200px);
        }
    }
}

输出

@-webkit-keyframes testanimation {
  0% {
    left: 0;
    -webkit-transform: translate(10px, 20px);
  }
  100% {
    left: 100%;
    -webkit-transform: translate(100px, 200px);
  }
}
@-moz-keyframes testanimation {
  0% {
    left: 0;
    -moz-transform: translate(10px, 20px);
  }
  100% {
    left: 100%;
    -moz-transform: translate(100px, 200px);
  }
}
@keyframes testanimation {
  0% {
    left: 0;
    transform: translate(10px, 20px);
  }
  100% {
    left: 100%;
    transform: translate(100px, 200px);
  }
}

2
这个怎么样:
@-webkit-keyframes some-animation {.mixi-frames;}
@-moz-keyframes some-animation {.mixi-frames;}
@-ms-keyframes some-animation {.mixi-frames;}
@-o-keyframes some-animation {.mixi-frames;}
@keyframes some-animation {.mixi-frames;}

.mixi-frames () {
    from {width: 254px;}
    to {width: 512px;}
}

你需要为每个动画都这样做。 引用自:http://radiatingstar.com/css-keyframes-animations-with-less

1
同时感谢Martin Turjak提供的出色答案,(感谢您)。我在Github上发布了一个Less mixin,它可以以灵活的方式生成keyframes和动画的css代码,而无需使用hack方法。你可以在这里找到它 github.com/kuus/animate-me.less
使用这个mixin,你可以编写以下代码来获得有效且跨浏览器兼容的css(请在github仓库中查看完整解释):
.animate-me(ComplexAnimation; 0.4s ease; '.complex-animation';
    '50%, 100%'; '%stransform: translateZ(-250px) rotateY(30deg)';
    70%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: .5; background:   green';
    30%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: .2; background: yellow';
    80%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: 1; background: red'
);

0

我认为你应该这样做

@-webkit-keyframes @name 
{
 code...
}

"@name"替换为@name

并在之后删除;

.keyframes(@name, @from, @to) {

你认为我在没有检查这个解决方案之前就提问了吗? - Lukas

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接