Can a sass @mixin accept an undefined number of arguments?
Variable Arguments
Sometimes it makes sense for a mixin to take an unknown number of arguments. For example, a mixin for creating box shadows might take any number of shadows as arguments. For these situations, Sass supports “variable arguments,” which are arguments at the end of a mixin declaration that take all leftover arguments and package them up as a list. These arguments look just like normal arguments, but are followed by ...
. For example:
@mixin box-shadow($shadows...) {
-moz-box-shadow: $shadows;
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
.shadows {
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
is compiled to:
.shadows {
-moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
-webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}
From : SASS official Documentation
So you basically just need to change your mixins declaration to look like this :
@mixin transition($var...)
-webkit-transition: $var
transition: $var
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;
}
Making a Sass mixin with optional arguments
A DRY'r Way of Doing It
And, generally, a neat trick to remove the quotes.
@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
-webkit-box-shadow: $top $left $blur $color #{$inset};
-moz-box-shadow: $top $left $blur $color #{$inset};
box-shadow: $top $left $blur $color #{$inset};
}
SASS Version 3+, you can use unquote()
:
@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
-webkit-box-shadow: $top $left $blur $color unquote($inset);
-moz-box-shadow: $top $left $blur $color unquote($inset);
box-shadow: $top $left $blur $color unquote($inset);
}
Picked this up over here: pass a list to a mixin as a single argument with SASS
How to define Sass mixins with variable arguments
You can set your second parameter to be false
as the default value, and do a @if
statement inside your mixin.
@mixin myMixin( $param1, $param2:false ){
@if $param2 == false{
// Do something
}
@else{
// Do something with both parameters
}
}
Edit: this a custom function I made to transform px unit into em unit. You can pass a list or a single value as parameter. You can also set a base and a line-height. Maybe you can find few tricks inside this function.
You can use it like this: emify(10px 16px, 16px)
.
This will output: 0.625em 1em
/**
*
* Emify
* Transform px unit into em
* defaults:
* base: 16
* usage:
* emify(unit)
* emify(unit, base)
* emify(unit, line-height, base)
* examples:
* emify(16px) = 1em
* emify(16px, 10px) = 1.600em
* emify(16px, 10px, 10px) = 1.600em / 1em
*
**/
@function emify( $target, $lineheight: null, $base: null ) {
@if $base == null and $lineheight == null { $base: 16 }
@if $base == null and $lineheight != null { $base: $lineheight }
[...]
}
Variable list of arguments in a LESS mixin
@rest
is not a keyword, its a sample identifier use to demonstate ...
. It could have any other name.
To fix your code:
.linear-gradient(@rest...) {
background: -webkit-linear-gradient(@rest);
background: -o-linear-gradient(@rest);
background: -moz-linear-gradient(@rest);
background: linear-gradient(@rest);
}
body > header {
.linear-gradient(red, yellow, blue);
}
You could replace @rest
with @arguments
inside the mixin as you use the entire input as a "variable arguments list". Then you could also omit the @rest
identifier altogether:
.linear-gradient(...) {
background: -webkit-linear-gradient(@arguments);
background: -o-linear-gradient(@arguments);
background: -moz-linear-gradient(@arguments);
background: linear-gradient(@arguments);
}
There's no difference between the 2 versions.
But all of that is not what you want at all. The 2 solutions above will result in a CSS that looks like this:
background: linear-gradient(red yellow blue);
That is because the values are interpreted as individual arguments, and are concatenated in a string with spaces.
What you need is this:
.linear-gradient(@colors) {
background: -webkit-linear-gradient(@colors);
background: -o-linear-gradient(@colors);
background: -moz-linear-gradient(@colors);
background: linear-gradient(@colors);
}
body > header {
.linear-gradient(red, yellow, blue;);
}
This tells LESS that the argument passed into the mixin is a single variable, with comma's inside. That translates to your required output.
How to count Sass mixin variable arguments
You can use the length
function:
@mixin my_func( $args... ) {
@if length($args) == 4 {
... output here ...
}
@else {
... output here ...
}
}
LESS Mixins with Optional Parameters - Skip Undefined Properties
Looks like I am able to leverage the Mixin Guards. By using the when not
and if not
operators nested inside the mixin, I can check for multiple parameters where the ,
separator acts as an or
.
When @blockEnd or @block are truthy, compile the following
.border(@border; @block: null; @blockEnd: null;) {
border: @border;
& when not(@blockEnd = null), not(@block = null) {
border-block-end: if(not (@blockEnd = null), @blockEnd, @block);
}
}
This will evaluate to:
// LESS
.container {
.border(@border: 1px solid red);
}
// CSS
.container {
border: 1px solid red;
}
It feels quite verbose, but it gets the job done.. Am I missing an easier approach, possibly?
Related Topics
Galaxy S4 Stock Browser CSS3 Border-Radius Support
Bootstrap 4.1 - to Get Grid System Only
CSS Overlapping Elements & Opacity Issue
How to Target CSS3 Columns Individually with Selectors
CSS Variables Don't Work in Microsoft Edge
How to Build a String in a Loop for a Dynamic Gradient
Responsive Google Maps V3 - Cannot Get 100% Height
Change the CSS of the Qna Bot Embedded as Webchat
Get Color Attribute from the Styles Table
Using Bootstrap Icons with Button_To "Delete" in Rails 3
How to Assign Custom CSS Class to Arbitrary Arbitrary Rows of H:Datatable
CSS Selector for Class Descendant Within a Class
Using Createmuitheme to Override Default Styles on Div'S, P'S, Body
Remove Underline from Part of a Link