Retrieving individual values within a list in Sass - sass

Say I've got something like this:
$padding = 5px 25px;
$border = 1px solid #f00;
Can I retreive the single values? Something like
$padding-vertical = $padding[0]; // returns 5px;
or:
$padding-vertical = $padding(top); // returns 5px
or:
$border-size = $border[border-width]; // return 1px
$border-color = $border(border-color); // return #f00
etc...
Is this possible?

The nth() function is the only way to retrieve specific items in a list, and it requires knowing its position.
$padding-vertical = nth($padding, 1); // returns 5px;
Because many shorthand properties don't require all values to be set, you might not get the results you're looking for. For the variables you've provided, this will work:
$border-size = nth($border, 1); // return 1px
$border-color = nth($border, 3); // return #f00

Related

Check if a variable is a color SCSS [duplicate]

This question already has answers here:
Sass - Check which kind of value a variable has
(2 answers)
Closed 2 years ago.
I would like to know if a variable is a valid color in a SASS function.
This is the first code I wrote, so I check if the variable is initialised.
#function get-valid-color($color) {
#if variable-exists($color) {
#return $color;
} #else {
#return inherit;
}
}
I would like to understand also if the variable is a valid color or not. Only in that case I would return the variable, otherwise I would return inherit.
This the expected output:
$primary-text = red;
$primary-bg = #000000;
$border-width = 4px;
color: get-color($border-width); // color: inherit;
background-color: get-color($primary-bg); // background-color: #000000;
color: get-color($primary-text); // color: red;
color: get-color($fake-variable); // color: inherit
Ideas, thanks.
There is a built-in method in SASS (type-of()) that might help to check if the current existing color is actually is a color or not, so you can check it like this:
#function get-valid-color($color) {
#if type-of($color) != color {
#return inherit;
} #else {
#return $color;
}
}

How to preserve units with SASS computed variable?

I try to create some relative font-size values that match "nearly" pixels sizes:
html { font-size: 62.5%; }
$font-10px: 1em/1.1em;
$font-11px: 1.1em/1.1em;
$font-12px: 12em/11em;
.x10 { font-size: $font-10px; }
.x11 { font-size: $font-11px; }
.x12 { font-size: $font-12px; }
However, the output of this sass snipet is:
.x10 {
font-size: 0.90909;
}
.x11 {
font-size: 1;
}
.x12 {
font-size: 1.09091;
}
As you can see, the unit (em) has been stripped.
This results in a incorrect value.
How should I declare my variables to contains the correct unit?
Dividing one length by another length always results in the unit being removed if the lengths are using the same units. So your options are:
Divide using one length and one integer: 1.1em / 1.1
Multiply the unit back on afterwards: 1.1em / 1.1em * 1em
Don't use division at all: 1em
Add PX to the end of your variable and surround the variable with #{ }. This is known as interpolation #{ } and treats the variable as plain css. Interpolation also helps to remove any spaces between the number and unit of measurement:
$base-font-size: 16;
body { font-size: (62.5% * base-font-size); }
$font-10px: 1em/1.1em;
$font-11px: 1.1em/1.1em;
$font-12px: 12em/11em;
.x10 { font-size: #{$font-10px}px; }
.x11 { font-size: #{$font-11px}px; }
.x12 { font-size: #{$font-12px}px; }
Result:
.x10 {
font-size: 0.90909px;
}
.x11 {
font-size: 1px;
}
.x12 {
font-size: 1.09091px;
}
Since you mentioned accessability in the SA talk, I recommend that you add one of the mixins in this blog post by Hugo Giraudel to your project to allow the use REM units while also providing backwards compatibility for older browsers.

Function to dynamically create classes from lists

Im fairly new to SASS and I'm confused by the way lists work. I have a multidimensional list like this:
$stylethemes: {
(15, bold, red),
(12, normal, blue)
}
I now want a function that makes a class for each list in $stylethemes and then puts the values of that list into that class. The output I want from the above list is this:
.theme1{
font-size: 15;
font-weight: bold;
color: red;
}
.theme2{
font-size: 12;
font-weight: normal;
color: blue;
}
Can anyone show me how I can do this? Thanks in advance.
The code to produce the desired results would look like this:
$stylethemes: (
(15, bold, red),
(12, normal, blue)
);
#for $i from 1 through length($stylethemes) {
.theme#{$i} {
font-size: nth(nth($stylethemes, $i), 1);
font-weight: nth(nth($stylethemes, $i), 2);
color: nth(nth($stylethemes, $i), 3);
}
}
However, you'll find this isn't particularly flexible. You're better off using mappings for the property/values so that you don't have to guarantee a specific order:
$stylethemes: (
(font-size: 15, font-weight: bold, color: red),
(font-size: 12, font-weight: normal, color: blue)
);
#for $i from 1 through length($stylethemes) {
.theme#{$i} {
#each $prop, $val in nth($stylethemes, $i) {
#{$prop}: $val;
}
}
}
Or
$stylethemes: (
theme1: (font-size: 15, font-weight: bold, color: red),
theme2: (font-size: 12, font-weight: normal, color: blue)
);
#each $theme, $properties in $stylethemes {
.#{$theme} {
#each $prop, $val in $properties {
#{$prop}: $val;
}
}
}
Youa re basically asking us to solve your pboelm, but fine, since SASS is very deep and fun to use and can be a bit daunting with its lack of map looping functions. I changed a couple of things but this is essentially it:
// first off, I decided to make your style themes a SASS map. This is useful because your
// your theme will be intricately linked to its name, making it easier to read
// you could to the same with the values, but for now I'll count them.
$stylethemes: (
theme-1 : (15, bold, red),
theme-2 : (12, normal, blue)
);
// first, we need to create a regular list we can loop through with a for loop
// map-keys returns a list we can use for that
$allthemes : map-keys($stylethemes);
// then we can run through all the themes by finding the theme name from the above list
#for $var from 1 through length($allthemes) {
// heres how we get the theme name
$theme : nth($allthemes, $var);
// heres how we get the values stored in your SASS map
$this : map-get($stylethemes, $theme);
// then I assign all your variables to vars, but its not necessary
$size : nth($this, 1);
$style : nth($this, 2);
$color : nth($this, 3);
// now print the theme name as a classname
.#{$theme}{
// then print the values - you could also use the above nth($this, n) to get them.
font-size: $size;
font-weight: $style;
color: $color;
}
}
I got all the function info from the SASS documentation site: http://sass-lang.com/documentation/Sass/Script/Functions.html, so have a look around there, there is a dedicated section for lists and maps. Have a look at lists and maps as they will be very useful for this kind of thing.

Sass color variable not working inside darken()

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%);
}
}
}
}

Store arbitrary strings in sassscript variables?

Is it possible to render arbitrary strings in scss? You can render property values:
/*source scss*/
$some-color: #123456;
a {color: $some-color;}
/*compiled css*/
a {color: #123456;}
or selectors/property names using #{} interpolation syntax:
/*source scss*/
$some-class: 'my-awesome-link';
$some-attribute: border;
a.#{$some-class} {#{$some-attribute}-color: #000;}
/*compiled css*/
a.my-awesome-link {border-color: #000;}
but I can't use the following:
/*source scss*/
$some-css: 'text-decoration:none;color:#000';
a {$some-css} //breaks
a {#{$some-css}} //breaks
This seems like vanilla string processing and something extremely trivial to allow. Am I overlooking a different syntax, or is it not possible in current scss?
The closest you can get to what you want is like this:
#mixin property-list($list) {
#each $i in $list {
#{nth($i, 1)}: nth($i, 2);
}
}
$links: color red, border (1px solid);
a {
#include property-list($links);
}
Compiles to:
a {
color: red;
border: 1px solid;
}

Resources