I'm introducing LESS to a large web app project to simplify my CSS. I've got a few CSS rules which apply transitions to a varying number of properties, for example:
.movable {
transition-property: top, left;
transition-duration: 0.2s;
transition-timing-function: ease;
}
.fadeAndStretchable {
transition-property: opacity, width, height, margin;
transition-duration: 1.5s;
transition-timing-function: ease-out;
}
(Note: I've omitted -webkit
, -moz
and -o
properties here for brevity: in reality each of these rules is 12 lines long rather than 3.)
Note that the values for transition-property
are comma-separated. This is unusual in CSS: multiple values are usually space-separated (as in border: 1px solid #f00
). LESS mixins can use the special @arguments
value to produce a space-separated list of all the mixin arguments - but is it possible to define a LESS mixin that takes a variable number of parameters and turns them into a comma-separated value list, suitable for transition-property
?
If necessary, I'm happy with a solution that requires two mixins: one for transition-property
and another for transition-duration
and transition-timing-function
. Here's what I've tried so far:
.transition-property() {
-webkit-transition-property: @arguments;
-moz-transition-property: @arguments;
-o-transition-property: @arguments;
transition-property: @arguments;
}
.movable {
.transition-property(top, left);
}
Result: LESS error ("No matching definition was found for '.transition-property(top, left)'")
.transition-property(@p1, @p2, @p3, @p4, @p5) {
-webkit-transition-property: @arguments;
-moz-transition-property: @arguments;
-o-transition-property: @arguments;
transition-property: @arguments;
}
.movable {
.transition-property(top, left);
}
Result: LESS error ("No matching definition was found for '.transition-property(top, left)'")
.transition-property(@p1:p1, @p2:p2, @p3:p3, @p4:p4, @p5:p5) {
-webkit-transition-property: @p1, @p2, @p3, @p4, @p5;
-moz-transition-property: @p1, @p2, @p3, @p4, @p5;
-o-transition-property: @p1, @p2, @p3, @p4, @p5;
transition-property: @p1, @p2, @p3, @p4, @p5;
}
.movable {
.transition-property(top, left);
}
Result: No LESS error but it generates a CSS rule -webkit-transition-property: top, left, p3, p4, p5
that the browser ignores because of the unrecognised properties.
I've tried various other approaches (e.g. passing the property as a string 'top,left'
) but all result in the same thing: either a LESS error or invalid CSS.
Is there any way round this? Or do I have to bite the bullet and define a set of mixins overloaded on arity, e.g.
.transition-property(@p1) {...}
.transition-property(@p1, @p2) {...}
.transition-property(@p1, @p2, @p3) {...}
.transition-property(@p1, @p2, @p3, @p4) {...}
etc.
I've managed to figure it out thanks to Luke Page pointing me towards the ...
syntax.
The solution was to use the following:
...
to allow variable parameters~
prefix to escape the resulting expression (i.e. stop LESS from enclosing it in a string)Phew. Here's the resulting mixin:
.transition-properties(...) {
-webkit-transition-property: ~`"@{arguments}".replace(/[\[\]]/g, '')`;
}
And here's the full version with a complete set of browser extensions:
.transition-properties(...) {
@props: ~`"@{arguments}".replace(/[\[\]]/g, '')`;
-webkit-transition-property: @props;
-moz-transition-property: @props;
-o-transition-property: @props;
transition-property: @props;
}