I have a map of maps:
$colors: (
'yellow': (
'10': #fcf4d6,
'20': #fddc69,
'30': #f1c21b,
'40': #d2a106,
'50': #b28600,
'60': #8e6a00,
'70': #684e00,
'80': #483700,
'90': #302400,
'100': #1c1500,
'hover': (
'10': #f8e6a0,
'20': #fccd27,
'30': #ddb00e,
'40': #bc9005,
'50': #9e7700,
'60': #755800,
'70': #806000,
'80': #5c4600,
'90': #3d2e00,
'100': #332600
)
)
...
My goal is to use a mixin that translates this to CSS properties, recursively.
I feel like in any other language, this would be easy (maybe I don't know enough Sass).
For example,
html {
#include my-mixin($colors);
}
would translate to:
html {
--yellow-10: #fcf4d6;
--yellow-20: #fddc69;
...
--yellow-hover-10: #f8e6a0;
...
}
I have gotten as far as to build the property name only:
#mixin define-css-properties($map, $name: "") {
#each $key, $value in $map {
#if is-map($value) {
#include define-css-properties($value, $name + "-" + $key);
} #else {
--#{$name + "-" + $key}: red;
}
}
}
I solved it.
#mixin define-css-properties($map, $name: "", $valueAccum: null) {
#each $key, $value in $map {
#if is-map($value) {
#include define-css-properties($value, $name + "-" + $key, map.get($value, $key));
} #else {
--#{$name + "-" + $key}: #{$value};
}
}
}
Would love to hear feedback or see alternatives.
Related
I was following this article https://www.sitepoint.com/better-solution-managing-z-index-sass/
But there is a missing link where it doesn't link the map-deep-get function back into the z function, and the demo doesn't work.
I've tried searching but found no help.
$z-layers: (
"goku": 9001,
"shoryuken": 8000,
"modal": (
"base": 500,
"close": 100,
"header": 50,
"footer": 10
),
"default": 1,
"below": -1,
"bottomless-pit": -9000
);
#function map-deep-get($map, $keys...) {
#each $key in $keys {
$map: map-get($map, $key);
}
#return $map;
}
#function z($layer) {
#if not map-has-key($z-layers, $layer) {
#warn "No layer found for `#{$layer}` in $z-layers map. Property omitted.";
}
#return map-get($z-layers, $layer);
}
Map-deep-get
Syntax
Dart Sass syntax:
#use "sass:list";
#use "sass:map";
#use "sass:meta";
#function map-deep-get($map, $keys...) {
$scope: $map; $i: 1;
#while (meta.type-of($scope) == map) and ($i <= list.length($keys)) {
$scope: map.get($scope, list.nth($keys, $i));
$i: $i + 1;
}
#return $scope;
}
Lib Sass syntax:
#function map-deep-get($map, $keys...) {
$scope: $map; $i: 1;
#while (type-of($scope) == map) and ($i <= length($keys)) {
$scope: map-get($scope, nth($keys, $i));
$i: $i + 1;
}
#return $scope;
}
How to use:
This map-deep-get function let's you acces as deeply nested values as you want and can also be used as a regular map-get function.
$exampleMap: (
"foo": foo,
"bar": (
"barfoo": barfoo,
"barbar": (
"barbarfoo": barbarfoo,
),
),
);
Codepen Demo
Not nested item:
#debug map-deep-get($exampleMap, "foo") //foo
Nested item:
#debug map-deep-get($exampleMap, "bar", "barfoo") //barfoo
Nested map:
#debug map-deep-get($exampleMap, "bar", "barbar") //("barbarfoo": barbarfoo)
Nested nested item:
#debug map-deep-get($exampleMap, "bar", "barbar", "barbarfoo") //barbarfoo
Actually, now days you can directly use map-get to get nested property value:
$exampleMap: (
"foo": 1px,
"bar": (
"barfoo": 6px,
"barbar": (
"barbarfoo": orange,
),
),
);
.h-6 {
background: map-get($exampleMap, "bar", "barbar", "barbarfoo");
}
https://www.sassmeister.com/gist/bf2c9476c254493f06fdd761f9d6e798
I have two SCSS maps call $my-map-1 and $my-map-2. Each map has the keys with their hex value. I wrote a function to return the key and the hex values ($key, $value) of each map separately.
After that, I wrote a #if condition with my function to check the map. I pass my map name to the function. If map there, check is the $key equal to the given name. If that true, pass the $valu of that $key to my color mixin. This is my code.
$my-map-1: (
map-1-color-1: #506c89,
map-1-color-2: #737373,
map-1-color-3: #2a3949,
map-1-color-4: #182028,
);
$my-map-2: (
map-2-color-1: #fff,
map-2-color-2: #000,
map-2-color-3: #ddd,
map-2-color-4: #ccc,
);
//the function to read te map and return the key and the value.
#function color-map($color-map) {
#each $key, $value in $color-map {
#return ($key, $value);
}
}
//mixin
#mixin color-mix($color){
color: $color;
}
//css classes from here
#if color-map($my-map-1) {
if($key == map-1-color-1) {
.my-class{
#include color-mix($color:$value);
}
}
}
You can use map-get method, it is very useful: http://sass-lang.com/documentation/Sass/Script/Functions.html#map_get-instance_method
This is an example of mixin. I pass as argument also your key: maybe it is better because you can check also others key names, if you need it:
$my-map-1: (
map-1-color-1: #506c89,
map-1-color-2: #737373,
map-1-color-3: #2a3949,
map-1-color-4: #182028
);
$my-map-2: (
map-2-color-1: #fff,
map-2-color-2: #000,
map-2-color-3: #ddd,
map-2-color-4: #ccc
);
#mixin color-map($color-map, $key-map) {
#each $key, $value in $color-map {
#if($key == $key-map) {
.my-class{
color: map-get($color-map, $key);
}
}
}
}
#include color-map($my-map-1, map-1-color-1);
Your output will be:
.my-class {
color: #506c89;
}
I'm trying to create a bunch of buttons using a loop and a map in SCSS, but I don't know if the following is possible. I couldn't find a direct answer when I searched for this.
Does anyone know if I can do this? And if I can, what in my syntax is wrong?
$button-variants:(
primary: 'primary',
secondary: 'secondary',
positive: 'positive',
negative: 'negative',
warning: 'warning'
);
#each $key,$val in $button-variants {
.c-button--#{$key} {
#include button($color-#{$key}, $color-#{$key}-highlight, true);
}
}
I'm receiving an error:
Error: Undefined variable: "$color-".
on line 54 of source/css/scss/04-components/_button.scss
>> #include button($color-#{$key}, $color-#{$key}-highlight, true);
Try something analogous to this:
/* Define the Sassy Map called $icons */
$icons: (
checkmark: a,
plus: b,
minus: c
);
/* For each key in the map, create a class */
#each $name, $value in $icons {
.icon--#{$name} {
content: $value;
}
}
And you'll get the following result:
/* For each key in the map, created a class */
.icon--checkmark {
content: "a";
}
.icon--plus {
content: "b";
}
.icon--minus {
content: "c";
}
I am trying to change color on click of change contrast (adding change-contrast class to body) in scss.
my static colors would be :
$primary-color-blue: #2aace2;
$mid-blue-color: #2695d2;
$dark-blue-color: #124b62;
on change contrast :
$primary-color-blue: #177eab;
$mid-blue-color: #1c6f9b;
$dark-blue-color: #124b62;
should be something like in sass
if(change-contrast) {
// console.log (get High Constrast Colors)
}
else {
// console.log (Static Colors)
}
Iam trying to do like below, but if i do like below i have to add to each and every class.
#mixin branding {
#each $brand in $brand_clr {
&.#{nth($brand,1)} {
$primary-color-blue: #177eab;
#content;
}
}
}
test {
background: $primary-color-blue;
#include branding {
background: $primary-color-blue;
}
}
Appreciate your help on this !!
Thanks
I think the solution comes across a well structured color map. You need to group colors by types (eg. static, contrasted). Then, use a mixin to avoid duplicating youself.
$colors:(
standard: (
primary-color-blue: #2aace2,
mid-blue-color:#2695d2,
dark-blue-color:#124b62
),
contrasted: (
primary-color-blue: #177eab,
mid-blue-color:#1c6f9b,
dark-blue-color:#124b62
)
);
#function get-color($key, $type: 'standard'){
#each $name, $color in map-get($colors, $type){
#if($key == $name){
#return $color
}
}
}
#mixin get-color($property,$color){
#{$property}: get-color($color);
#at-root body.contrasted & {
#{$property}: get-color($color, contrasted);
}
}
.className{
#include get-color(background-color, primary-color-blue)
}
This will output:
.className {
background-color: #2aace2;
}
body.contrasted .className {
background-color: #177eab;
}
I'm trying to set some multiple background #mixin with SASS, so this is my code:
#mixin background_multiplied($background_1, $background_2: false, $background_3: false) {
$params: url('../#{$background_1}') $atributes;
#if $background_2 != false {
$params: url('../#{$background_1}') $atributes, url('../#{$background_2}') $atributes;
}
#if $background_3 != false {
$params: url('../#{$background_2}') $atributes, url('../#{$background_2}') $atributes, url('../#{$background_3}') $atributes;
}
#each $attr in $atributes {
#if $attr == position_horizontal {
$position_horizontal: center
}
#if $attr == position_vertical {
$position_vertical: top
}
#if $attr == bg_repeat {
$bg_repeat: no-repeat
}
#if $attr == bg_size {
$bg_size: auto
}
}
background: $params;
}
Something is not right bc i have error (Line 210: Undefined variable: "$atributes".)
Can anybody help me? Much thx.
The error speaks for itself. You've got the $atributes variable called everywhere, but it's never declared.