1

I wrote a LESS mixin that automates CSS transitions with proper engine prefixes.

.Transition(@Property, @Timing){
    -moz-transition: @Property @Timing linear;
    -webkit-transition: @Property @Timing linear;
    -o-transition: @Property @Timing linear;
    transition: @Property @Timing linear;
}

Unfortunately, I can't specify a select group of styles to animate. I can only specify one specific style or "all." If I try using the same mixin multiple time to throw more stylesinto the mix, the transition property just gets overwritten. For example:

.class { .Transition(top, .2s); .Transition(opacity, .2s); .Transition(box-shadow, .2s); }

results in:

.class {
    -moz-transition: box-shadow, .2s;
    -webkit-transition: box-shadow, .2s;
    -o-transition: box-shadow, .2s;
    transition: box-shadow, .2s; 
}

How can I write a mixin that lets me apply a flexible amount of values to one style?

thiirteen
  • 103
  • 1
  • 8

3 Answers3

2

Merge support

LESS v1.5 introduced support for merging rules by suffixing properties with +

The merge feature allows for aggregating values from multiple properties into a comma or space separated list under a single property. merge is useful for properties such as background and transform.

...

Example:

.mixin() {
  box-shadow+: inset 0 0 10px #555;
}
.myclass {
  .mixin();
  box-shadow+: 0 0 20px black;
}

Outputs:

.myclass {
  box-shadow: inset 0 0 10px #555, 0 0 20px black;
}

Semi-colon support

LESS v1.4(?) introduced support for multiple parameters with semi-colons. This allows each parameter to include literal commas without requiring multiple parameters.

Using comma as mixin separator makes it impossible to create comma separated lists as an argument. On the other hand, if the compiler sees at least one semicolon inside mixin call or declaration, it assumes that arguments are separated by semicolons and all commas belong to css lists:

  • two arguments and each contains comma separated list: .name(1, 2, 3; something, else),
  • three arguments and each contains one number: .name(1, 2, 3),
  • use dummy semicolon to create mixin call with one argument containing comma separated css list: .name(1, 2, 3;),
  • comma separated default value: .name(@param1: red, blue;).
Example
.transition(@args) {
    -webkit-transition: @args;
    -moz-transition: @args;
    -o-transition: @args;
    transition: @args;
}
.selector {
    .transition(.2s top, .2s opacity, .2s box-shadow;);
    //                            this is required -^
}

Pre semi-colon support

Supporting multiple arguments with commas pre-semicolon support is a bit harder than it would seem at first, largely because less strips commas from @arguments. I've started a ZLESS project on github where I've added a lot of mixins to simplify working with LESS.

This is the code I use for transition (without the compiler flag):

.transition(@a, @b: X, ...) {
    //http://stackoverflow.com/a/13490523/497418
    @args: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;
    -webkit-transition: @args;
    -moz-transition: @args;
    -o-transition: @args;
    transition: @args;
}

It would be used as:

.selector {
    .transition(.2s top, .2s opacity, .2s box-shadow);
}
Community
  • 1
  • 1
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • So, there is no way to do what I want, out of the box? – thiirteen Mar 12 '13 at 21:48
  • @thiirteen, the arguments for the CSS property needs to have comma separated values. There's no way that I am aware of that you could call a mixin multiple times and have it produce CSS correctly as a single style declaration. – zzzzBov Mar 12 '13 at 23:19
  • 1
    @zzzzBov the (new?) "Comma" thing, where you add a `+` to the end of the real CSS property name, is a sort-of good way to do this. It's kind-of ugly because you have to re-invoke the whole mixin for each member of the list, but it does make it at least possible. – Pointy Aug 28 '14 at 00:30
  • @Ponty, >"It's kind-of ugly because you have to re-invoke the whole mixin for each member of the list" - Yoda suggests to use loops for that. – seven-phases-max Aug 28 '14 at 15:08
1

I think if you separate the "property" for your transition, that might work out!

for example :

.transitionProperty ( @property1, @property2, @property3) {
   -moz-transition-property : @property1, @property2, @property3;
   -o-transition-property : @property1, @property2, @property3;
   -webkit-transition-property : @property1, @property2, @property3;
   transition-property : @property1, @property2, @property3;
}

Or something like that. I think it's a matter worth thinking for ;)

Ali Tabibzadeh
  • 193
  • 1
  • 2
  • 13
1

You basically need to pass them as an escaped string. So modify your code:

.Transition(@transString){
    -moz-transition: @transString;
    -webkit-transition: @transString;
    -o-transition: @transString;
    transition: @transString;
}

Then use it like this:

.Transition(~"top .2s linear, opacity .2s linear, box-shadow .2s linear");

Which produces this:

-moz-transition: top .2s linear, opacity .2s linear, box-shadow .2s linear;
-webkit-transition: top .2s linear, opacity .2s linear, box-shadow .2s linear;
-o-transition: top .2s linear, opacity .2s linear, box-shadow .2s linear;
transition: top .2s linear, opacity .2s linear, box-shadow .2s linear;
ScottS
  • 71,703
  • 13
  • 126
  • 146