What Sass Mixin returns? - sass

In a programming language like javascript, even though I don't make any a "returned" result in the end, but it still returns a value, "undefined".
In case of Sass, I know that #mixin does not "return" anything like #function.
However, it "actually" returns nothing at all?
If it returns something actually (something like "undefined" or "void"), then what it returns?

I'm not sure I get the question but...
Mixins lets you create reusable CSS declarations (CSS content) 'called' using #include.
Unlike functions you can't assign mixins to variables as they do not produce a return value (throws an error).
#function fs($value){
#return $value;
}
#mixin fs($value){
font-size: $value;
...
}
.class { // returns value
font-size: fs(16px); // => 16px;
}
.class { // generates properties and values
#include fs(16px); // => font-size: 16px; ...
}
$var: fs(16px); // will work (function)
$var: #include fs(16px); // won't work (mixin)

Try to read this article and this one, you have some answer :
"They obtain full CSS rules where properties that are dynamic will be passed into arguments"
So when you #include a #mixin in your code, it will return CSS rules.

Related

SASS/SCSS, how to access a property/method in a dynamic way from a partial file?

Let's say for instance we have the next sass partial file:
//_colors.scss
$foo: red;
And we "use" it on another file:
//test.scss
#use './colors'
.test{
color: colors.$foo;
}
All good, but what if I would like to use/get the value in a dynamic way within a mixin? something like:
//test.scss
#use './colors'
#mixin getColor($type){
color: colors[$type]; //JavaScript example, * don't actually work *.
or
color: #{colors.{$type}; * don't work neither *
//The above returns `color: colors.foo` instead of `color: red` on compilation.
or
color: colors.#{$type}; * doesn't work neither *
}
.test{
#include getColor(foo);
}
Is it possible? thanks for the help!
For a color, I really much prefer a function so it can be used on any property (color, background-color, border, box-shadow...)
I usually declare a string equivalent to variable names, then define them inside a map. Finally this map is accessible via a dedicated function.
Something like
//_colors.scss
#use 'sass:map';
$favoriteRed: "favoriteRed";
$favoriteYellow: "favoriteYellow";
$favoriteBlue: "favoriteBlue";
$MyColors: (
$favoriteRed: #c00,
favoriteYellow: #fc0,
$favoriteBlue: #0cf
);
#function my-color($tone: $favoriteRed) {
#if not map.has-key($MyColors, $tone) {
#error "unknown `#{$tone}` in MyColors.";
}
#else {
#return map.get($MyColors, $tone);
}
}
This _colors.scss generates no code at all, it can be imported anywhere at no cost.
Then, in a specific style file:
//test.scss
#use './colors' as *;
//inside a mixin
#mixin special-hue-component($tone){
div.foo {
span.bar {
border-color: my-color($tone);
}
}
}
//or directly
.foobartest {
color: my-color($favoriteBlue);
}

#mixin format is it ok to not have ()?

Learning about #mixin and I came across this code. How come the hover-not-disabled on the first line is not followed by () and is it ok to do this? Thanks in advance!
#mixin hover-not-disabled {
&:not([disabled]):hover {
#content;
}
}
.button {
border: 1px solid black;
#include hover-not-disabled {
border-color: blue;
}
}
Its fine. It won't cause any errors, since (…) is meant to contain the arguments which when using a #mixin are usually needed, however in this case the editor wants to pass the mixin into mutliple elements and then edit the #content.
From a subjective point of view, I'd recommned to always include the () for the sake of consistency even if they would be empty, so when quickly scanning the code, nothings seems odd.
So this would be my approach, but generally spoken, it's totally fine to leave them in such cases.
#mixin hover-not-disabled() {…}
#include hover-not-disabled();

SASS wrap mixin to add extra argument

I am working with a mixin called button with the following signature:
#mixin button($expand: false,
$background: $button-background,
$background-hover: $button-background-hover,
$color: $button-color, $style: solid)
I would like to create a mixin to wrap this one called sized-button, that takes an additional parameter to indicate the size of the button based on a $button-sizes map.
The map looks like this:
$button-sizes: (
tiny: 0.6rem,
small: 0.75rem,
default: 0.9rem,
large: 1.25rem,
);
I was hoping to use variable arguments so that I don't have to redefine the arguments for the button mixin. For example, this was my first attempt:
#mixin sized-button($size: default, $buttonArgs...) {
#if (map-has-key($button-sizes, $size)) {
#include button($buttonArgs);
font-size: map-get($button-sizes, $size);
}
#else {
#warn "Invalid button size";
}
}
However, doing this does not seem to work. For example, if I pass one of the button arguments to the sized-button mixin, I get an error:
#include sized-button($size: large, $expand: true);
Mixin sized-button has no parameter named $expand
Is it possible to do what I'm trying to do?

Giving default arguments to mixins when there is more than one variable

I am trying to make a #mixin where I want to give a default value to the first variable but not to the second variable.
#mixin myCoolFont($color:purple, $size) {
color: $color;
font-size: $size;
}
Now when I call that mixin I do something like this:
p {
#include myCoolFont(white, 63px)
}
When compiling it outputs an error that says $size must come before any other arguments.
Please, tell me, what am I doing wrong?
You just do as error says, it will work, simple change order of arguments so that last argument(s) are those with default values. In your case:
#mixin myCoolFont($size, $color:purple) {
color: $color;
font-size: $size;
}
p {
#include myCoolFont(63px, white)
}

How to use !important keyword in a mixin?

I can't get Sass to output the !important keyword with a mixin, I've tried:
#include font-size($font-size-sml) !important;
And:
#include font-size($font-size-sml !important);
It always throws an error.
EDIT
I ended up with this which works fine:
#mixin font-size($font-size, $sledge-hammer: "") {
font-size: $font-size #{$sledge-hammer};
font-size: ($font-size / $base-font-size)+rem #{$sledge-hammer};
line-height: ceil($font-size / $base-line-height) * ($base-line-height / $font-size);
}
You can't add !important to whole mixin in SASS (It is possible in LESS I think) like you're trying to do in first example.
Second example works for me (you can pass !important with a parameter), I mean, if you use $font-size-sml directly as a property value it works, so maybe check your syntax.
But if it's really not working for you, you can do something with flag, set a important_flag as a mixin parameter and then use if-else statement in mixin. Something like this:
#mixin large-text($prop, $is_imp: false) {
#if $is_imp == false {
font-size: $prop;
} #else {
font-size: $prop !important;
}
}
Maybe it's not a glamorous way to do it, but it works ;-)
You can use the if(condition, when-true, when-false) function.
So the code will be simplest and compact:
#mixin large-text($size, $isImportant: false) {
font-size: $size if($isImportant, !important, null);
}

Resources