With Sass mixins we’re able to pass a list of arguments to set the values of properties. For example, the following mixin uses four variables as arguments to define the display, padding and margin properties of an element.
@mixin display ($disp, $padding, $l-margin, $r-margin) { display: $disp; padding: $padding; margin-left: $l-margin; margin-right: $r-margin; }
When including this mixin, we’ll always need to pass a value for each variable, otherwise it will output an error message.
.nav__link { @include display(inline-block, 10px, 20px, 0); ... }
This often forces us to zero out certain properties we don’t need, or unnecessarily redefine their initial values. So, what if we don’t need to pass a value for every variable?
Optional arguments in mixins
Arguments can be optional if we provide default values for them:
@mixin display ($disp, $padding:0, $l-margin:0, $r-margin:0) { ... }
This makes the $padding
, $l-margin
and $r-margin
arguments optional when including the mixin. But again, depending on the values passed, the mixin may output unnecessary CSS, or repeat a lot of code in the output CSS.
Using null
Good news! Sass also supports a null
data type, which seems to work best for optional arguments in mixins.
With null
, we can pass a variable with no value and it gets excluded from the CSS output unless we assign a value to it when including the mixin. Let’s rewrite the mixin passing null
as the default value:
@mixin display ( $disp, $padding: null, $r-margin: null, $l-margin: null) { display: $disp; padding: $padding; margin-left: $l-margin; margin-right: $r-margin; }
The null
value works wonderfully in this case because we’re still able to define optional arguments without the unnecessary CSS output. So now, if we pass two values, it will only output those declarations to the CSS.
.nav__item { @include display(inline-block, $l-margin: 20px); }
See null
in action in this SassMeister gist:
Play with this gist on SassMeister.
Null with math
Keep in mind that using null
in math operations will return an error if no value gets passed. For instance:
@mixin display ( $disp, $padding: null, $l-margin: null) { display: $disp; padding: $padding; margin-left: $l-margin; margin-bottom: $l-margin * 2; } .nav__link { @include display(inline-block, 10px); }
This returns an Invalid null operation: "null times 2"
error in the output since there’s no value defined for $l-margin
––we can’t add, subtract, multiply or divide a number by null
.
As we learned, Sass’ null
data type is particularly useful for DRYing out a mixin’s CSS output. You can learn more about using null
in Sass mixins in our new Advanced Sass course, and in our short course on creating a Compass extension!
Hi,
What abt can something like the following be done:
/* Margin mixin */
@mixin margin-all($top, $right, $bottom, $left)
{ margin-top: $top;
margin-right: $right;
margin-bottom: $bottom;
margin-left: $left; };
/* Btn mixin */
@mixin link-btn ($padding, $margin) {
padding: $padding;
@include margin-all($margin);
}
@include link-btn(20px, (null null 20px null));
OR
@include link-btn(20px, ($top:null, $right: null, $bottom: 20px, $left: null));
If not, how to do it
Your code not work correct code is here
@mixin btn-g($tp,$rm,$lr,$bt){margin-top: $tp; margin-right: $rm; margin-left: $lr; margin-bottom: $bt}
@mixin btn-p($pp,$mm){padding: $pp; @include btn-g($mm…); }
.bob2 {@include btn-p(10px,10px 8px 9px 7px); font-family: $font_he01}
I love the simple approach to this. I am always compelled to put in a default, even if the parameter is optional. Null seems to be the most streamlined approach for values that might or might not be present, but the whole math issue will come back to bite me every once in awhile. That’s why I opt to put in ($foo: false) and do an @if check instead. Maybe a little overly robust at times, but has saved me future hassle.
All in all, great article. Cheers, Guil!
Or I guess I could have just replied with: “Ya, what James Steinbach said.”
Another way to handle the “null with math” issue is to wrap each of your mathed outputs in an if statement. Makes for longer mixins but fewer errors:
@if $s-margin {
margin-bottom: $l-margin * 2;
}
Sassmeister Gist: http://sassmeister.com/gist/e99e8e31c05e98c6104a
Great, wasnt aware of the null feature =)