How to Define a Less Mixin to Generate a Transition-Property with a Variable Number of Parameters

Can I define a LESS mixin to generate a transition-property with a variable number of parameters?

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
  • Backticks for JavaScript evaluation
  • Variable string interpolation
  • A ~ prefix to escape the resulting expression (i.e. stop LESS from enclosing it in a string)
  • Good old regular expressions

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;
}

Using LESS mixin for a transition on multiple properties

It could be more simple if you don't not need those defaults, but well:

@import "for";

.transition(@args...) when (default()) {
.for(@args); .-each(@value) {
.transition(@value);
}
}

.transition(@value) {
transition+: @property @duration @delay @timing;
@n: length(@value);
.-(); .-() {
@property: extract(@value, 1);
@duration: extract(@value, 2);
@delay: extract(@value, 3);
@timing: extract(@value, 4);
}
.-() when (@n < 2) {@duration: .4s}
.-() when (@n < 3) {@delay: 0s}
.-() when (@n < 4) {@timing: cubic-bezier(.16, .53, .15, .99)}
}

Where imported "for" utility can be found here.

And for vendor prefixes use autoprefixer.


Alt. imp. just in case, an alternative implementation almost similar to above but using another approach to apply "default" values:

@import "for";

.transition(@args...) when (default()) {
.for(@args); .-each(@value) {
.transition(@value);
}
}

.transition(@value) {
@n: length(@value);
& {transition+ : extract(@value, 1)}
& when (@n > 1) {transition+_: extract(@value, 2)}
& when (@n < 2) {transition+_: .4s}
& when (@n > 2) {transition+_: extract(@value, 3)}
& when (@n < 3) {transition+_: 0s}
& when (@n > 3) {transition+_: extract(@value, 4)}
& when (@n < 4) {transition+_: cubic-bezier(.16, .53, .15, .99)}
}

Less CSS: Mixins with Variable Number of Arguments

See my answer here: Multiple properties are getting treated as separate arguments in mixins

Summary: use this mixin for variable number of arguments:

.transition (@value1,@value2:X,...)
{
@value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;

-webkit-transition: @value;
-moz-transition: @value;
-ms-transition: @value;
-o-transition: @value;
transition: @value;
}

LESS: Mixin with a unique argument to manage css3 transitions

You can use string escaping and interpolation like this:

.links-transition (@arg:"color 1s, border-color 1s") {
@color-time: ~"@{arg}";
-webkit-transition:@color-time;
-moz-transition:@color-time;
-ms-transition:@color-time;
-o-transition:@color-time;
transition:@color-time;
}

a {
color:red;
.links-transition ("color 2s, border-color 2s");
}

it will return this CSS:

a {
color: red;
-webkit-transition: color 2s, border-color 2s;
-moz-transition: color 2s, border-color 2s;
-ms-transition: color 2s, border-color 2s;
-o-transition: color 2s, border-color 2s;
transition: color 2s, border-color 2s;
}

hope this does what you want.

For more ideas: there are some additinal approaches/solutions that you can find on SO, like this two for example:

  • Less CSS: Mixins with Variable Number of Arguments

  • Multiple properties are getting treated as separate arguments in mixins


Update: in LESS 1.4 beta it works the way you wanted to do it:

.links-transition (@color-time: color 1s, border-color 1s;) {
-webkit-transition:@color-time;
-moz-transition:@color-time;
-ms-transition:@color-time;
-o-transition:@color-time;
transition:@color-time;
}

a {
color:red;
.links-transition (color 2s, border-color 2s;);
}

has the same output as the above solution. Comma separated argunets are possible since 1.3.2, however they can apparently not include whitespaces.

Using Less mixin variable as a property value

The feature is being added (according to the LESS devs), but still hasn't shipped. I'd recommend following the commits on GitHub.

Interesting reading in this issue > https://github.com/less/less.js/issues/36

pass property name as an argument in a mixin LESS

I think this is what you are trying to do:

//A simple Border Mixin to start
.borderMixin(@color: #ddd){
border: 1px solid @color;
}
//Using the Mixin
.border{
.borderMixin(@color: #ddd);
&-right {
.borderMixin(@color: #F01);
}
&-left {
.borderMixin(@color: #000);
}
}

So first I've declared the Mixin helper to be used and then I used it and re-use it exending the class name with the & character

That will output this in your CSS:

/*********
*The resulted css code:
*/
.border {
border: 1px solid #dddddd;
}
.border-right {
border: 1px solid #ff0011;
}
.border-left {
border: 1px solid #000000;
}

UPDATE:


+Harry suggests this:

.borderMixin(@position: left, @color: #ddd){
border-@{position}: 1px solid @color;
}

.border{
width: 200px;
.borderMixin(right,#222);
.borderMixin(left,#222);
}

How do you make a LESS mixin for gradients with a variable number of stops?

No Separate Variable Needed

All that you need is to make sure you use a semicolon as a separator for the parameters, even if that happens to just be only one parameter you are passing. So this works:

LESS

@white: #fff;
.gradient (@origin: left, @fallback: @white, @stops){
background-color: @fallback;
background: -webkit-linear-gradient(@origin, @stops) @fallback no-repeat;
background: -moz-linear-gradient(@origin, @stops) @fallback no-repeat;
background: -ms-linear-gradient(@origin, @stops) @fallback no-repeat;
background: -o-linear-gradient(@origin, @stops) @fallback no-repeat;
background: linear-gradient(@origin, @stops) @fallback no-repeat;
}

.test {
.gradient(@stops: #fff 0, #000 20px, #000 20px, #f00 20px;)
} |
this final semicolon
causes the commas to
become list separators
instead of parameter
separators making the whole
thing part of one variable

CSS Output

.test {
background-color: #ffffff;
background: -webkit-linear-gradient(left, #ffffff 0, #000000 20px, #000000 20px, #ff0000 20px) #ffffff no-repeat;
background: -moz-linear-gradient(left, #ffffff 0, #000000 20px, #000000 20px, #ff0000 20px) #ffffff no-repeat;
background: -ms-linear-gradient(left, #ffffff 0, #000000 20px, #000000 20px, #ff0000 20px) #ffffff no-repeat;
background: -o-linear-gradient(left, #ffffff 0, #000000 20px, #000000 20px, #ff0000 20px) #ffffff no-repeat;
background: linear-gradient(left, #ffffff 0, #000000 20px, #000000 20px, #ff0000 20px) #ffffff no-repeat;
}

Multiple properties are getting treated as separate arguments in mixins

I'd suggest using LESS's escape function, i.e.:

a:link, a:visited { 
color: green;
opacity: .5;
font-size: 1em;
}

a:hover {
color: red;
opacity: 1;
font-size: 2em;
.transition(e("font-size, color"));
}

And though it seems that LESS accepts that, it will only animate the last property in the comma-separated string you send through. A pity.



Related Topics



Leave a reply



Submit