4

I have a property @keyframes, I compiled with autoprefixer to add the needed prefixes.

What I would like to do, is to add an argument to the animation name (or wherever is possible) to change a value of properties into the keyframes key.

This is what I have right now :

@keyframes loader {
  0% { transform: translate(0, -50%) rotate(0deg); }
  100% { tranform: translate(0, -50%) rotate(360deg); }
}

And basically what I would like to do :

@keyframes loader(@transform) {
  0% { transform: @transform rotate(0deg); }
  100% { tranform: @transform rotate(360deg); }
Harry
  • 87,580
  • 25
  • 202
  • 214
jeremybarbet
  • 890
  • 1
  • 15
  • 28
  • I don't know why Curt had deleted his answer. It was almost perfect. All that you need to do is wrap the keyframes rule within a mixin and pass the parameter to the mixin.. – Harry Oct 09 '15 at 08:48

1 Answers1

8

Passing arguments to @keyframes cannot be done directly in Less. We can however wrap the whole @keyframes rule within a parent mixin, pass the argument to that mixin and use it within the frames.

.loader(@transform){ /* wrapper mixin which accepts input parameter */
   @keyframes loader {
     0% { transform: @transform rotate(0deg); }
     100% { transform: @transform rotate(360deg); }
   }
}

.loader(translate(0, -50%)); /* mixin call */

(Curt had provided an answer initially but had deleted it for reasons unknown to me.)


Just in case you are interested, generic keyframe mixins can also be written in Less like given below.

Sample 1:

.generickeyframe(@name; @from; @to){ /* takes name, from frame rules, to frame rules */
  @keyframes @name{
    0% { @from();}
    100% { @to();}
  }
}
.generickeyframe(loader; {transform: translate(0,-50%) rotate(0deg)}; 
            {transform: translate(0,-50%) rotate(360deg)});

Sample 2:

.keyframefromto(@name; @from; @to){
  @keyframes @name{
    0% { transform: @from;}
    100% { transform: @to;}
  }
}
.keyframefromto(loader; translate(0,-50%) rotate(0deg); translate(0,-50%) rotate(360deg));

If multiple frames are required to be present within the @keyframes rule, we could make use of array-list and loops like in the below snippet. This mixin takes the name of the animation, the list of frames (their percentage numbers) and the properties for each frame (in the form of rulesets) as parameters.

.generickeyframe(@name; @framelist; @frameprops){
  @keyframes @name{
    .loop-framelist(@index) when (@index <= length(@framelist)){
      @framepos: extract(@framelist, @index) * 1%;
      @{framepos}{
        @props: extract(@frameprops, @index);
        @props();
      }
      .loop-framelist(@index + 1);
    }
    .loop-framelist(1);
  }
}
.generickeyframe(loader; 
                0,25,50,75,100; 
                {transform: translateX(10px);},
                {transform: translateX(20px);},
                {transform: translateX(50px);},
                {transform: translateX(20px);},
                {transform: translateX(10px);}
                );

Compiled CSS:

@keyframes loader {
  0% {transform: translateX(10px);}
  25% {transform: translateX(20px);}
  50% {transform: translateX(50px);}
  75% {transform: translateX(20px);}
  100% {transform: translateX(10px);}
}
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Thanks, that's works perfectly. For your last exemple, that's not as generic as it should be. I could add as many keyframes I want and not depends of only 0% and 100%. – jeremybarbet Oct 09 '15 at 09:32
  • True @jbr If there are multiple frames then a loop with associative array would be more useful. Let me see if I can come up with a quick sample for it. – Harry Oct 09 '15 at 09:32
  • 1
    @jbr: I have added a version with loops into the answer and it may be more useful for you :) – Harry Oct 09 '15 at 09:52