Syntax for if/else condition in SCSS mixin - conditional-statements

Hi I'm trying to learn SASS/SCSS and am trying to refactor my own mixin for clearfix
what I'd like is for the mixin to be based on whether I pass the mixin a width.
thoughts so far (pseudo code only as I will be including other mixins)
#mixin clearfix($width) {
#if !$width {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}
here's how I thought I might call it, but it's not working.
#include clearfix();
or
#include clearfix(100%)
or
#include clearfix(960px)
I'd appreciate any help on the best or right way to do this!

You can assign default parameter values inline when you first create the mixin:
#mixin clearfix($width: 'auto') {
#if $width == 'auto' {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}

You could try this:
$width:auto;
#mixin clearfix($width) {
#if $width == 'auto' {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}
I'm not sure of your intended result, but setting a default value should return false.

You could default the parameter to null or false.
This way, it would be shorter to test if a value has been passed as parameter.
#mixin clearfix($width: null) {
#if not ($width) {
// if width is not passed, or empty do this
} #else {
display: inline-block;
width: $width;
}
}

Related

Sass check if value is passed to mixin

Please help me to modify mixin and create compatible function.
Here is my mixin, it can accept optonal parameter !important true or false, and if !important is true then output height as
height: 16px !important; for example:
#mixin svg-size($size, !important: true) {
svg {
height: $size foo();
width: $size foo();
}
}
Call mixin:
#include svg-size(16px, true);
Output:
svg {
height: 16px !important;
width: 16px !important;
}
I also need a proper name for that kind of function
How about conditionally-important as the function name and use some basic at-rules for flow control returning !important if true?
#function conditionally-important ($important) {
#if $important {
#return !important;
}
#return null;
}
#mixin svg-size($size, $is-important: true) {
svg {
height: $size conditionally-important($is-important);
width: $size conditionally-important($is-important);
}
}
// Calling as important
#include svg-size(16px, true);
// Output
svg {
height: 16px !important;
width: 16px !important;
}
// Calling as not important
#include svg-size(16px, false);
// Output
svg {
height: 16px;
width: 16px;
}

Is it possible to output embedded mixin rules without passing them as a mixin parameter?

.mixin(#param) {
#{param} & {
#thoseRules(); // color: blue
}
}
button {
display: block;
.mixin('param') {
color: blue;
}
}
Is something like the above possible in LESS without passing the property block as a parameter of the mixin?

Set "min-width" or "max-width" in a media query passing a parameter to a mixin

I would like to make dynamic MIN/MAX suffix in properties defined in a Less MediaQuery.
I wrote this code but it does not compile:
#screen-md: 800px;
.MEDIAQUERY(#min-max, #size)
{
#media screen and (#{min-max}-width: #size)
{
#{min-max}-width:100px;
}
}
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
While #{min-max}-width:100px; is a correct syntax, equivalent applied in Mediaquery definition is not allowed, but I need to set sometime "max-width" value, and others "min-width" value in my media queries. How to obtain this?
Option 1: (Using a variable and interpolation)
You can do it like below
.MEDIAQUERY(#min-max, #size) {
#mediaQuery: ~"screen and (#{min-max}-width: #{size})";
#media #mediaQuery {
#{min-max}-width:100px;
}
}
Option 2: (Using Guards)
You can use guards in the mixin like below to check what was the value that was passed for the #min-max parameter and then output the appropriate CSS based on it.
.MEDIAQUERY(#min-max, #size){
& when (#min-max = min) {
#media screen and (min-width: #size) {
min-width:100px;
}
}
& when (#min-max = max) {
#media screen and (max-width: #size) {
max-width:100px;
}
}
}
When the above mixin is called like below (with either of the options mentioned above):
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
div{
background-color: red;
.MEDIAQUERY ( #min-max: min, #size: #screen-md );
}
it would compile into the below CSS:
header {
background-color: blue;
}
#media screen and (max-width: 800px) {
header {
max-width: 100px;
}
}
div {
background-color: red;
}
#media screen and (min-width: 800px) {
div {
min-width: 100px;
}
}

How to declare same style for #media and descendant selector?

I need to define same style for elements under a media query and descendant by another class.
Perfect solution in LESS could be the following [pseudo-code]:
.foo
{
color:red;
.example &,
#media (min-width:800px)
{
color:blue;
}
}
that should be desirable that would be compiled into:
.foo {
color: red;
}
.example .foo {
color: blue;
}
#media (min-width: 800px) {
.foo {
color: blue;
}
}
THIS SYNTAX IS INCORRECT but, do you have some suggestion to solve my problem?
Nope, selectors and #media queries are too different language entities (despite having similar {} syntax) so you can't combine those with comma like in your example.
So to get it DRY (assuming that shared style has more than one property of course) you'll need a mixin (or sort of), for example:
.foo {
color: red;
.somename() {
color: blue;
}
.example & {.somename}
#media (min-width: 800px) {.somename}
}
Also see Passing Rulesets to Mixins examples (if you need even more generic solution).
Thanks to #seven-phases-max suggestion, I finally found a possible solution using Detached Ruleset:
#screen-xs: 480px;
#screen-sm: 769px;
#screen-md: 992px;
#screen-lg: 1200px;
.MEDIAQUERY(#only-media, #min-max, #size, #RULES)
{
#screen-width:~"#{screen-#{size}}";
#mediaQuery: ~"screen and (#{min-max}-width: #{screen-width})";
#media #mediaQuery { #RULES(); }
& when (#only-media = false) {
.#{size} & { #RULES(); }
}
}
.foo_media-and-class
{
color:red;
.MEDIAQUERY(#only-media:false, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:false, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
.foo_only-media
{
color:red;
.MEDIAQUERY(#only-media:true, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:true, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
This solution go beyond and offer other options:
Possibility to set a custom value of screen width for media query,
Pass MIN/MAX value of property used in media query (Try to pass "max" instead of "min" calling .MEDIAQUERY mixin)
Toggling generation of simple media query or media query + descendant selector, through #only-media boolean.
I think your comma might be causing the error.
.foo {
color:red;
.example & {
color:blue;
#media (min-width:800px) {
color:blue;
}
}
}
This is proper syntax to output the following:
.foo {
color: red;
}
.example .foo {
color:blue;
}
#media (min-width:800px) {
.example .foo {
color:blue;
}
}

Is it possible to nest variables within variables in SASS?

I have a mixin that accepts an argument that I want to pass into a variable.
#mixin my_mixin($arg) {
background-color: $state-#{$arg}-text;
}
Interpolation of variable names is currently not possible in SASS. Here is the issue that discusses.
However, you may use interpolation of placeholders:
%my-dark-styles {
background-color: #000;
}
%my-white-styles {
background-color: #FFF;
}
#mixin my_mixin($arg) {
#extend %my-#{$arg}-styles;
}
.header {
#include my_mixin("dark");
}
.footer {
#include my_mixin("white");
}
This compiles to:
.header {
background-color: #000;
}
.footer {
background-color: #FFF;
}
Since Sass 3.3 you can use maps also https://sass-lang.com/blog/sass-33-is-released
Here is an example:
$state-light-text : #FFFFFF;
$state-dark-text : #000000;
$color-map: ( //create a array to support the two colors light and dark
light: $state-light-text,
dark: $state-dark-text
);
#each $color-key, $color-var in $color-map {
.myclass--#{$color-key} { //will generate .myclass--light .myclass--dark
background-color: $color-var; // equal $state-light-text or $state-dark-text
}
}
It will compile into:
.myclass--light {
background-color: #FFFFFF;
}
.myclass--dark {
background-color: #000000;
}