Multiple properties are getting treated as separate arguments in mixins
Asked Answered
P

4

18

I'm trying to write a mixin, but I can't seem to get the arguments working the way I want: multiple properties are getting treated each as a separate argument.

Current Code

.transition(@property: all, @time: 1s, @timing: ease-in-out) {
    -moz-transition: @property @time @timing;
    -webkit-transition: @property @time @timing;
    -o-transition: @property @time @timing;
    transition: @property @time @timing;
}

a {
    .transition(color, opacity, .5s);
}

Desired Output

a {
    -moz-transition: color, opacity .5s ease-in-out;
    -webkit-transition: color, opacity .5s ease-in-out;
    -o-transition: color, opacity .5s ease-in-out;
    transition: color, opacity .5s ease-in-out; 
}

Actual Output

a {
    -moz-transition: color opacity .5s;
    -webkit-transition: color opacity .5s;
    -o-transition: color opacity .5s;
    transition: color opacity .5s;  
}

Any ideas?

Passed answered 1/4, 2011 at 7:57 Comment(3)
dont forget to add a comma after @property in your mixinJalapa
see my answer for a clean solution based on LESS optional syntax for passing arguments to a mixin.Fredericton
note that your desired output syntax is not what i believe you intend. the transition shorthand property must be a comma-separated list of complete single transitions. see MDNLumbricalis
O
37

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.

Operetta answered 2/4, 2011 at 2:27 Comment(3)
Thanks a lot! It generates all the properties for me (only difference from your example is I put the transition mixin inside just "a").Passed
Thanks Chris. Just ran in to this issue (multiple properties) and your solution worked perfectly!Resuscitator
I tried using the multi variable solution above, but because I am using wp-less to process in variables from WordPress theme settings it was throwing an error trying to evaluate the@value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; but this works perfectly! ThanksBlackandblue
T
25

Using the solution found here works with one AND multiple arguments:

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

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

Using it this way:

.transition(color, opacity .5s ease-in-out);

yields:

-webkit-transition: color, opacity .5s ease-in-out;
-moz-transition: color, opacity .5s ease-in-out;
-ms-transition: color, opacity .5s ease-in-out;
-o-transition: color, opacity .5s ease-in-outt;
transition: color, opacity .5s ease-in-out;
Tunisia answered 21/11, 2012 at 9:53 Comment(5)
Thanks for this, I've been looking for something like this for awhile now! Can't say I understand it all (X is just a nonsense character to be stripped out later if it defaults?) but it works great.Islam
I have trouble with this solution, it only works well if you use a comma. Without a comma the result is like this transition: all, 500ms ease-in-out, 100ms; For .transition(all 500ms ease-in-out 100ms)Bolt
@Robert: Just tried it in VS2013 with WebEssentials 2013, on lesstester.com and jsfiddle.net - all works as expected. See it working here: jsfiddle.net/dMk23 Edit: It just happened to me too - after hitting "Tidy Up" in jsfiddle. The reformat adds a space right before \sX/g - and that breaks it. Check if that happend to you too.Tunisia
It was my fault: I had not the same parameters, I had (...) instead of yours. Thanks for your advice :)Bolt
sad that this won't compile with lessphp compilerBrimmer
G
7

If you want to pass a comma-separated list as an argument to mixin, you can simply use a semicolon to separate arguments.

Code below works as desired with the mixin you defined:

a {
    .transition(color, opacity; .5s);
}
Garganey answered 12/10, 2013 at 15:48 Comment(1)
Works fine, thanks. But not with customized functions like .transition-value(...) {transition: @arguments}Bolt
L
2

Less mixins have the ability to use semicolon-separated arguments (as well as comma-separated). They recommend you always use semicolons.

If a semicolon is present in a list of arguments when the mixin is called, everything between semicolons will be considered as arguments, even if those things have commas in them. This allows you to pass a comma-separated list as ONE argument. If a semicolon is NOT present, it will treat commas as argument separators.

.transition(@property: all; @time: 1s; @timing: ease-in-out) { // NOTE THE SEMICOLONS
    transition: @property @time @timing;
}

a {
    .transition(color,opacity; .5s); // SEMICOLON AFTER 'opacity'
}
b {
    .transition(color,opacity, .5s); // COMMA INSTEAD
}

output:

a {
    transition: color,opacity .5s ease-in-out;
}
b { 
    transition: color opacity .5s; // invalid syntax
}

Note that the syntax of the shorthand transition property must be a comma-separated list of single transitions. So b has an invalid value, and a has two transitions, in which the unspecified values default to their initial value:

  1. color 0s ease 0s
  2. opacity .5s ease-in-out 0s

This is likely not what you intended. (It looks like you wanted color .5s ease-in-out 0s and opacity .5s ease-in-out 0s.)


Now you might be wondering, "how do I pass a comma-separated list as a single argument, when there are no other arguments?" Simply append a dummy semicolon at the end of the list.

.transition(@property: all; @time: 1s; @timing: ease-in-out) {
    transition: @property @time @timing;
}

b {
    .transition(color,opacity;); // DUMMY SEMICOLON AFTER ARGUMENT
}
i {
    .transition(color,opacity); // MISSING SEMICOLON
}

output:

b {
    transition: color,opacity 1s ease-in-out; // 'color,opacity' is the first argument
}
i {
    transition: color opacity ease-in-out; // 'color' is 1st arg, 'opacity' is 2nd arg
}

Again, syntax for i is invalid, and b has two transitions:

  1. color 0s ease 0s
  2. opacity 1s ease-in-out 0s
Lumbricalis answered 4/5, 2016 at 15:10 Comment(2)
Cool! I'm guessing it's a more recent feature.Passed
@OscarBroman Depends on how you define "recent." It's been around since at least 2013; see Michael Ryback's answer.Lumbricalis

© 2022 - 2024 — McMap. All rights reserved.