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
How to Float an Element Left with Full Height of the Wrapper
CSS Fade Out Horizontal Rule/Line Styled Div Effect Without Images
CSS Rotation with Respect to a Reference Point
Svg "Fill: Url(#....)" Behaving Strangely in Firefox
What Is the Current State of Sub-Pixel Accuracy in the Major Browsers
CSS Transition Does Not Work on Top Property in Ff
How to Make Angled Tab Like This Using CSS
How to Get Div Height 100% Inside Td of 100%
What's a @Media Rule Without a Media Type Do
Match Colors in Fecolormatrix Filter
Jerky CSS Transform Transition in Chrome
What Is the Different Between Clearfix Hack and Overflow:Hidden VS Overflow:Auto
Css: Fixed with Horizontal Menu, with Variable Width Tabs, Using Ul
In Visual Studio 2010, How to Easily Comment Out Lines in CSS