Access SASS multidimensional list key - css

I have a multidimensional list:
$color-set: (bg-color #888, border-color #444, active-bg-color #666, hover-bg-color #808080)
Currently I access each by using:
$color-set: (#888, #444, #666, #808080)
#div {
background: nth($color-set, 1)
}
Is there a way to use the key instead like:
#div {
background: $color-set(bg-color)
}
so I don't have to remember the order of colors in the list?

All you have is a list of lists, and lists only have numeric indexes. You would have to write a function that iterates over your list and compares the first element to some string argument. This is not something I recommend as it offers no benefit over just using ordinary variables.
#function find-value($list, $key) {
#each $item in $list {
#if ($key == nth($item, 1)) {
#return nth($item, 2);
}
}
#return false;
}
Sass does not currently support mappings, but will soon: https://github.com/nex3/sass/issues/642

Just use a separate variable for each color?
$bg-color: #888;
$border-color #444;
div {
background: $bg-color
}

Related

How to pass a variable to lightness($color)? SCSS

I want to create a function which will change color based on background-colorlightness(), but get an error
Argument $color of lightness($color) must be a color
When I setup color: set-color(#000000); everything is okay, but I need to setup varibable ($background-color). Is there is a way to achieve it?
#function set-color($color) {
#if (lightness($color) >= 50) {
#return #000;
}
#else {
#return #FFF;
}
}
$background-color: attr(data-color);
background-color: $background-color;
color: set-color($background-color);
From the code it looks like u are using data-color attribute is down tag.
Either add the attribute to proper element in html
Or hard code $background-color to some value
i.e. replace
$background-color: attr(data-color)
with
$background-color: #000000

Accessing specific value from SASS nested list

I have the following sass variable:
$color-config:( "white": #FFF,
"black": #303133
);
and i would like to access the 'black' value (#303133) without make a loop. Something like that:
body
color: $color-config("black")
(i know, its completely wrong, its just to explain what i want)
You can use SASS's maps to store values inside variables:
$color-config:(
white: #FFF,
black: #303133
);
Then use map-get() to access it (see here):
content: map-get($color-config, white); # will return #FFF
In other words, don't use double quotes " around your variable name.
$color-config:(
'white': #FFF, //quotes are important
'black': #303133
);
#function colors($value) {
#return map-get($color-config, $value)
}
.white-font {
color: colors('white')
}

SASS | #for and #each loop printing values from a list issues

I'm using sass to print values from a list with a #each and #for loop but when ever i try to print one by one and compile that gathered values in the css it takes all the values in the list even using a nth('', $n) function.
I'm using the following code and gulp as my task runner.
// SASS CODE
$btn-default: darken(#DDD, 5%);
$btn-alert: red;
$btn-class: "btn-default", "btn-alert";
$btn-color: $btn-default, $btn-alert;
#each $btn in $btn-class {
.#{unquote($btn)} {
#for $i from 1 through length($btn-color) {
background-color: nth($btn-color, $i);
}
}
}
/* CSS CODE : OUTPUT */
.btn-default {
background-color: #d0d0d0;
background-color: red; }
.btn-alert {
background-color: #d0d0d0;
background-color: red; }
I'm a little bit stuck in a project i tried from different ways in the sass and when i don't get the values it just return an error instead.
Instead of introducing an inner #for loop that will inevitably render two properties in each ruleset, try using a single loop:
#for $i from 1 through length($btn-class) {
#{nth($btn-class, $i)} {
background-color: nth($btn-color, $i)
}
}
In the long run however, I would recommend using maps instead. This way you have a clear association between class names and colors which will avoid potential mistakes in larger lists of elements:
$buttons: (
btn-default: $btn-default,
btn-alert: $btn-alert
);
#each $class, $color in $buttons {
.#{$class} {
background-color: $color;
}
}

Using a variable from list in a function in each - scss [duplicate]

I've got list of colors and I would like to use darken() on them like so:
$innerPagesBgColors: "#6B46C1", "#2980B9", "#FD5456", "#000";
.foo {
color: darken(nth($innerPagesBgColors, 3), 5%);
}
But I get this error:
$color: "#FD5456" is not a color for `darken'
I tried interpolating the nth() portion but that didn't help either.
The problem is that darken function requires a color as first argument and, instead, you're trying to pass a string.
type-of(#6B46C1); // returns color
type-of("#6B46C1"); // returns string
So you should remove all quotes in $innerPagesBgColors:
$innerPagesBgColors: #6B46C1, #2980B9, #FD5456, #000;
In my case I solved with this.
#each $name, $color in $set_colors{
// check type-of before
#if (type-of($color) == 'color'){
.color-#{$name}{
color: #{$color};
}
.background-#{$name}{
background-color: $color;
&:hover{
background-color: darken($color, 10%);
}
}
}
}

Creating variable groups in Sass

On the site I'm working on we were using Scaffold, which is a PHP-based system similar to Sass. It also can process Sass functions\files. Unfortunately that system is now abandonware, and we are looking on a way to move completely to Sass. There is one big feature with Scaffold though that I'm not finding a way to port to Sass, the variable groups.
Variable in Scaffold can be organized in groups and used with a point-separated markup. For example I would define them as:
#variables vargroup1{
variable1: ####;
variable2: ####;
variable3: ####;
variable4: ####;
}
And later use on the code as, for example.
body{ width: vargroup1.variable1; margin: vargroup1.variable2 + 10;}
This helps development a lot, since you can group together variables from a system and reading the CSS files you can easily know what to reference. I didn't find anything like that on the Sass documentation, anyone knows if it is possible? Or if there is anyway using Mixins to do this?
Thanks
I came across this somewhat clunky solution (see Chris Eppstein's reply) using zip and index. Apparently a maintainer of SASS added these built-in functions in response to a similar question.
To quote his reply:
$border-names: a, b, c;
$border-widths: 1px, 1px, 2px;
$border-styles: solid, dashed, solid;
$border-colors: red, green, blue;
$borders: zip($border-widths, $border-styles, $border-colors);
#function border-for($name) {
#return nth($borders, index($border-names, $name))
}
#each $name in $border-names {
.border-#{$name} {
border: border-for($name);
}
}
Would generate:
.border-a { border: 1px solid red; }
.border-b { border: 1px dashed green; }
.border-c { border: 2px solid blue; }
The "naming your variables" comes from the list "-names" at the top; you then use the index of a desired variable name from that variable list to get the nth value from another variable lists. zip is used to mush separate lists together, so that you can retrieve the same index from all lists at the same time. Wrapping that behavior in a function makes it easier to retrieve a set.
There is no equivalent in Sass. But I can think in two workarounds:
1) Sass lists and its related list functions.
Your code could look like the following:
$variables = 40px 30px 20px 10px;
body {width: nth($variables, 1); margin: nth($variables, 2) + 10;}
It's not the same because list indexes can't be strings, so you haven't any way to name your variables.
2) Define a custom function. Look at Function Directives section in Sass reference
#function variables($variable_name) {
#if ($variable_name == 'variable1') {
#return 40px;
} #else if ($variable_name == 'variable2') {
#return 30px;
}
}
body {width: variables('variable_1'); margin: variables('variable_2') + 10;}
This way is less intuitive and uglier but you can 'name your variables'.
You could use the scss/sass map function:
#use "sass:map";
$variables: (
"variable1": ####;
"variable2": ####;
"variable3": ####;
"variable4": ####;
}
body {
width: map.get($variables, "variable1");
margin: map.get($variables, "variable2") + 10;
}
Documentation
You can use SASS lists a it's related functions on a way similar to that:
// List order: top, bottom, left, right, width, height, ...
$Header: 10px,auto,10px,auto,100%,50px;
$Footer: auto,0px,0px,auto,100%,20px;
#function getVar($variable,$name:top){
$var_index:1;
#if $name==bottom {
$var_index:2;
} #else if $name==left {
$var_index:3;
}
// Continue de if else for each property you want.
return nth($variable,$var_index);
}
That way calling something like:
getVar($Header,left)
Should return the value of the left property for the list of Header, but changing it to getVar($Footer,top) would return the value for the top property of the "Footer Group" (Footer List of Values).
That works for the time of using the values, but a the definition, you must follow the exact order and cannot leave any empty value, the nearest to an empty value that I found is #{''} what means "Empty String with no quotes", an empty value, but is added to the CSS.

Resources