Why can't I use variable inside #include in my Sass loop? - css

So let's say I have the following mixins:
#mixin type-h1 {
font-size: 36px;
font-weight: bold;
}
#mixin type-h2 {
font-size: 28px;
font-weight: bold;
}
#mixin type-h3 {
font-size: 24px;
font-weight: bold;
}
Now I created utility classes:
.type-h1 {
#include type-h1;
}
.type-h2 {
#include type-h2;
}
.type-h3 {
#include type-h3;
}
All good so far. Now I would like to simplify my code and generate the utility classes using Sass loops. This is what I have:
$variable: 1, 2, 3;
#each $value in $variable {
.type-h#{$value} {
#include type-h$variable;
}
}
Anyone has an idea why this loop doesn't work?

You can create map with variables:
$vars: (1: 36px, 2: 28px, 3: 24px);
Then combine mixins into one:
#mixin types($value) {
font-size: $value;
font-weight: bold;
}
And finally you can generate your utilities by:
#each $size, $value in $vars {
.type-h#{$size} {
#include types($value);
}
}
Here is link to Codepen.io with example

Related

What is the cause of this failure to make a SCSS mixin with an optional parameter?

I need a SCSS mixin to make borders with. In this mixin, the $position variable, should be optional:
#mixin border($position, $width, $style, $color) {
#if $position {
border-#{$position}: $width $style $color;
} #else {
border: $width $style $color;
}
}
This is necessary so that I can use it in these 2 types of cases:
.box {
#include border('bottom', 1px, solid, #999) /*with position*/;
}
and
.button {
#include border(1px, solid, #999); /*without position*/
#include border-radius(9999999px);
padding: .5rem .75rem;
font-size: 14px;
}
For the second case, the compiler throws the error:
Mixin border is missing argument $color.
What am I doing wrong?
You can use default parameter for $position. I used the false boolean for default variable.
#mixin border($width, $style, $color, $position: false) {
#if $position {
border-#{$position}: $width $style $color;
} #else {
border: $width $style $color;
}
}
And you can use like this:
.button {
#include border(1px, solid, #999);
padding: 0.5rem 0.75rem;
font-size: 14px;
}
If you don't send any parameter, it enters else state (like above). If you send a position parameter, it enters the if state. Like this:
.button {
#include border(1px, solid, #999, right);
padding: 0.5rem 0.75rem;
font-size: 14px;
}
Also, keep in mind that optional parameters must come after mandatory parameters. This is a rule.

How to import a scss file inside a scss class

I want to add a different theme when i add "dark-theme" class to body. My implementation looks like this:
#import '../../../../node_modules/angular-grids/styles/material.scss';
.app-dark {
#import '../../../../node_modules/angular-grids/styles/material-dark.scss';
}
Without any luck. Any clue on how to do this?
There are two methods in order to do that. Both of them include mixins.
meta.load-css
The sass:meta feature gives the ability to do what you want.
Say you have this scss file with a theme:
//theme/_code.scss
$border-contrast: false !default;
code {
background-color: #6b717f;
color: #d2e1dd;
#if $border-contrast {
border-color: #dadbdf;
}
}
you can include that code inside another scss file like so:
// other-theme.scss
#use "sass:meta";
body.dark {
#include meta.load-css("theme/code",
$with: ("border-contrast": true));
}
This will result in the following css:
body.dark code {
background-color: #6b717f;
color: #d2e1dd;
border-color: #dadbdf;
}
You can read more about this feature here
old fashioned mixin
But you can do basically the same thing if you use mixin and include.
So, let's say you have this class you want to import into another class:
.title {
font-size: 2em;
font-weight: bold;
}
And another sass file with another theme:
.dark-theme {
.title {
font-size: 2em;
font-weight: bold;
color: white;
}
}
You can use a scss mixin and import it into both files:
mixin.scss
#mixin shared-items() {
.title {
font-size: 2em;
font-weight: bold;
}
}
then, in the theme files:
white-theme.scss
#import './mixin.scss';
/* will be included as is without a parent class */
#include shared-items;
dark-theme.scss
#import './mixin.scss';
/* will be included inside the dark-theme class */
.dark-theme {
.title {
color: white;
}
#include shared-items;
}
this will generate this css:
.title {
font-size: 2em;
font-weight: bold;
}
.dark-theme {
.title { color: white; }
.title {
font-size: 2em;
font-weight: bold;
}
}
Notice that you can also pass parameters to mixin and use them as functions.
So you can easily pass colors and use them with your theme variables.
for example:
# an example of giving a color to a placeholder mixin:
#mixin nk-placeholder($color: #C4C4CC) {
&::-webkit-input-placeholder {
color: $color;
font: inherit;
}
&::-moz-placeholder {
color: $color;
font: inherit;
}
&:-ms-input-placeholder {
color: $color;
font: inherit;
}
&:-moz-placeholder {
color: $color;
font: inherit;
}
&::placeholder {
color: $color;
font: inherit;
}
}
# same thing as above
#mixin shared-items($text-color: black) {
.title {
font-size: 2em;
font-weight: bold;
color: $text-color;
}
}
.white-theme {
#include shared-items;
}
.dark-theme {
#include shared-items(white);
}

Conditional SASS Variables using mixin's

I am currently using this mixin:
#mixin isMobile() {
html[data-browser*="Mobile"] & {
#content;
}
}
And I want to use this mixin to conditionally apply to a variable, like below:
$div-height: 20px;
#include isMobile() {
$div-height: 10px;
}
I know this is not the proper way of doing it, and I've also tried the following below with no success. How can I properly try this conditional? Thanks!
#if (html[data-browser*="Mobile"]) {
$div-height: 20px;
} #else {
$div-height: 10px;
};
The conditional part has to be in the mixin itself.
#mixin isMobile($type) {
$div-height: 0;
html[data-browser*="Mobile"] {
#if($type == 'A'){
$div-height: 20px;
}
#else{
$div-height: 10px;
}
height: $div-height;
#content;
}
}
#include isMobile('B'){
color:black;
}
/*Output*/
html[data-browser*="Mobile"] {
height: 10px;
color: black;
}

Change all variable value based on body class

I am working on theme based localisation. For that I am getting class on body tag for each localisation.
I need to change all variables value based on that class
For more Understanding
$a: #000;
$b= Arial;
if body has class Australia then
$a: #ff0000;
$b: 'Roboto';
Please no js code only by scss
Using #import and !default variables
// ––––––––––––––––––––––––––––––––––––––
// _style.scss
// underscore added to prevent compilation
// ––––––––––––––––––––––––––––––––––––––
$color : red !default;
$font-family: Arial !default;
.foo { color: $color; }
.bar { font-family: $font-family; }
// ––––––––––––––––––––––––––––––––––––––
// style.scss (compile file)
// ––––––––––––––––––––––––––––––––––––––
// redefine variables
$color: blue;
$font-family: Roboto;
// add wrapper if needed (will be added to all selectors)
.australia {
#import '_style.scss';
}
The following example uses a map to define different theme values. The mixin will wrap each selector in a class (the map key) and create global variables to be used inside each selector.
$theme-map:(
'.australia': (color: blue, font-family: Roboto),
'.denmark' : (color: red, font-family: Arial)
);
#mixin theme {
#each $class, $map in $theme-map {
#{$class} & {
$color: map-get($map, color) !global;
$font-family: map-get($map, font-family) !global;
#content;
}
}
}
.foo {
#include theme {
color: $color;
font-family: $font-family;
}
}
.bar{
#include theme {
background-color: $color;
}
}
Output:
.australia .foo {
color: blue;
font-family: Roboto;
}
.denmark .foo {
color: red;
font-family: Arial;
}
.australia .bar {
background-color: blue;
}
.denmark .bar {
background-color: red;
}
PS. in the near future CSS variables will ease this type of work using variable inheritance.
.australia {
--color: red;
--font-family : Arial;
}
.denmark {
--color: blue;
--font-family : Roboto;
}
.foo {
color: var(--color);
font-family: var(--font-family);
}
.bar {
backgound-color: var(--color);
}

SASS issue with calling mixin

My SASS code:
// rem calculator
#function calculateRem($size) {
$remSize: $size / 16px;
#return #{$remSize}rem;
}
#mixin fontsize($size) {
font-size: $size; //Fallback in px
font-size: calculateRem($size);
}
// variables
$font-size-regular: fontsize(16px);
// css
body {
font-size: $font-size-regular;
}
This outputs: font-size: fontsize(16px);
Using #include fontsize(16px); does work. but I want to put it in a variable if possible
You may do this
// rem calculator
#function calculateRem($size) {
$remSize: $size / 16px;
#return #{$remSize}rem;
}
#mixin fontsize($size) {
font-size: $size; //Fallback in px
font-size: calculateRem($size);
}
// variables
$font-size-regular: 16px;
// css
body {
#include fontsize($font-size-regular);
}

Resources