Using model attributes for the page style on Rails [duplicate] - css

I have a list in SASS, and I'm trying to access on of the items by using bracket notation:
$collection[1];
but that gives me an error.
Is there any other way to do this?
Why do I want to do this?
I have a list of colors that have to be set on different elements according to a colors assigned to them by the server. The markup has numbered classes (color-0, color-1, etc.). Here's the CSS I'm aiming for:
.color-0 { color: red }
.color-1 { color: orange }
.color-2 { color: green }
.color-3 { color: blue }
/* many more, with more complex colors... */
Instead of writing it all by hand, I figured I could use a SASS collection with a loop:
$color-collection: ('red', 'orange', 'green', 'blue');
$color-count: length($color-collection);
#for $i from 0 to $color-count {
.color-#{$i} {
color: $color-collection[ $i ];
}
}
but this just gives me the following error:
Syntax error: Invalid CSS after "...color-collection": expected ";", was "[ $i ];"
How can I accomplish this?

$color-collection: ('red', 'orange', 'green', 'blue');
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: unquote(nth($color-collection, $i+1));
}
}
Use nth(), also unquote() if you want to pass quoted strings.
Though, I personally wouldn't:
$color-collection: (red, rgba(50,50,80, .5), darken(green, 50%), rgba(blue, .5));
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: nth($color-collection, $i+1);
}
}
Because then you can pass any color object.

You can use #each rule instead of #for, which is more semantic, faster, and it makes the code shorter:
$color-collection: (red, orange, green, blue);
#each $color in $color-collection {
.color-#{$color} {
color: $color;
}
}
Or if you prefer you can use $color-collection list directly into the #each directive:
#each $color in red, orange, green, blue {
.color-#{$color} {
color: $color;
}
}
As #bookcasey says is preferable to use unquoted strings because then you can pass any color object or function
Sass reference for #each directive

just came across this and tested bookcasey's answer, which works well but I wanted to use the color name as the class instead; I found that this code works as I needed.
$colors: ( 'black', 'white', 'red', 'green', 'blue' );
#for $i from 0 to length($colors) {
$thisColor: unquote(nth($colors, $i+1));
.color-#{$thisColor} {
color: $thisColor;
}
}
using the #{...} allows you to use functions as well, so if you need to use an arbitrary name that may not be used directly in the rules you could use
#for $i from 0 to length($colors) {
.color-#{unquote(nth($colors, $i+1))} {
// some rules that don't actually use the var
// so there's no need to cache the var
}
}
output:
.color-black { color: black; }
.color-white { color: white; }
.color-red { color: red; }
// etc..
Hope this helps someone else!

I had similar problem and tried Alex Guerrero solution. Didn't work form me cause output was like .color-gray:{gray}; instead of .color-1:{gray};.So I modified it a bit and it looks like this:
$color-pallete: (gray, white, red, purple)
$i: 0
#each $color in $color-pallete
.color-#{$i}
color: $color
$i: $i + 1
Oh, ye. I use SASS, not SCSS.

Related

Is it possible to create a loop to cycle through a map however stop at a certain index in the map ? - SASS

I have a color theme map with five colors and I would like to create a mixin to accept a number argument which would be the stopping point. Then the mixin would execute the loop however stop the map loop when it reaches the mixin argument number.
Tried to read up on this however could not find any answers or solutions to get this to happen.
Code Example:
// color map
$colors: (
"r": red,
"b": blue,
"g": green,
"y": yellow,
"o": orange,
)
Current Situation: The each loop keeps cycling through the map until it reaches the end. Hence it will create 5 selectors with their background-colors as the values in the map.
#mixin color_theme($map) {
#each $col, $color in $map {
&.#{$col} {
background-color: $color;
}
}
}
Goal: To create a mixin with a loop to cycle only to a fixed number of values in the map.
You could use index (related answer: SASS - get map item value by item index) to get the map index number and then use it to stop the loop at a certain number:
// color map
$colors: (
"r": red,
"b": blue,
"g": green,
"y": yellow,
"o": orange
);
#mixin color_theme($map, $stop) {
#each $col, $color in $map {
$i: index($map, $col $color);
#if ($i <= $stop){
&.#{$col} {
background-color: $color;
}
}
}
}
div{
#include color_theme($colors, 4);
}
Your output:
div.r {
background-color: red;
}
div.b {
background-color: blue;
}
div.g {
background-color: green;
}
div.y {
background-color: yellow;
}

SASS/SCSS #each multiple arrays

I am trying to write a sass mixing using the values from two arrays to output my button classes. Not sure if what I am trying to do is possible at all.
So I have two arrays:
$buttonNames: ('black', 'primary', 'red', 'green', 'orange');
$buttonColors:(black, blue, red, green, orange);
and then my mixin is:
#mixin underlineButton($class, $name, $size, $color: black) {
.#{$class}-underline-#{$name} {
background-color: transparent;
border-bottom: $size + px solid $color;
border-radius: 0;
font-size: .75rem;
}
}
and then I do an #each loop for the names, and attempted to nest another loop inside this to get the colors. Obviously this isn't working! Just wondering if it is even possible.
#each $name in $buttonNames {
#each $color in $buttonColors {
#include underlineButton('btn', $name, 3, $color)
}
}
The desired output would be something like:
.btn-underline-black {
background-color: transparent;
border-bottom: 3px solid black;
border-radius: 0;
font-size: .75rem;
}
// .btn-underline-* for the rest of the matching keys and colors
Here's a DEMO
If you need to keep your values separate, in 2 lists, then you can...
// loop over $buttonNames
#each $buttonName in $buttonNames {
// Find the current index of $buttonNames...
$index: index($buttonNames, $buttonName);
// ... to pull the right from $buttonColors
#include underlineButton('btn', $buttonName, 3, nth($buttonColors, $index));
}
However, using a map is a little easier.
$buttons: (
'black': black,
'primary': blue,
'red': red,
'green': green
);
#each $buttonName, $color in $buttons {
#include underlineButton('btn', $buttonName, 3, $color)
}
$buttons: ('black', $black),
('primary', $primary),
('red', $red),
('green', $green);
#each $buttonName, $color in $buttons {
#include underlineButton('btn', $buttonName, 3, $color)
}

Using SCSS variable inside a variable

I want to use a SCSS loop as below:
#each $var in dark, purple, green, cyan, silver, white {
.text-#{$var} {
color: nth($color-, $var);
}
.btn-#{$var} {
background-color: nth($color-, $var);
}
}
in order to use the following variables:
$color-dark: #0D0E1E;
$color-purple: #333366;
$color-green: #33cc99;
$color-cyan: #00cccc;
$color-silver: #ccc;
$color-white: #fff;
but it is not working.
$color-#{$var} was not working as well. Can I do this?
nth gets an item in a list. The first argument is the list, the 2nd is an index in the list. Also SASS thinks anything with a $ is a variable, so $color- is a variable. You haven't defined $color- as a variable, and that's not your intended use.
DOCS.
But you can get your desired result with a map...
DEMO
$color-dark: #0D0E1E;
$color-purple: #333366;
$color-green: #33cc99;
$color-cyan: #00cccc;
$color-silver: #ccc;
$color-white: #fff;
$colors: (
dark: $color-dark,
purple: $color-purple,
green: $color-green,
cyan: $color-cyan,
silver: $color-silver,
white: $color-white
);
#each $name, $val in $colors {
.text-#{$name} {
color: $val;
}
.btn-#{$name} {
background-color: $val;
}
}

sass #each loop with multiple lists

developing in scss
I have the two variable lists:
$ids: 21, 33, 73;
$colors: #fff, #000, #333;
and the following #each loop.
#each $id, $color in ($ids, $colors) {
.category--#{$id},
.post--#{$id} {
color: #{$color};
}
}
I want to display the following
.category--21,
.post--21 {
color: #fff
}
.category--33,
.post--33 {
color: #000
}
.category--73,
.post--73 {
color: #333
}
But I'm getting this instead
.category--21,
.post--21 {
color: 33;
}
.category--#fff,
.post--#fff {
color: #000;
}
Unsure of my structure. Obviously I have much longer variables lists (just added 3 to each one for demo purposes).
Any constructive feedback welcome. Thanks
Based on my understanding, I think #each is not the correct option for you as you don't have the key and value pair as one item. Below is what the documentation says about #each: (emphasis is mine)
The #each directive can also use multiple variables, as in #each $var1, $var2, ... in <list>. If <list> is a list of lists, each element of the sub-lists is assigned to the respective variable.
As you can see from the above statement, in your case the $ids would be treated as one list and the $colors would be treated as another. It means that
1st iteration $id is 21, $color is 33 and 73 not assigned
2nd iteration $id is #fff, $color is #000 and #333 is not assigned.
It might be better for you to use the #for loop like in the below snippet:
$ids: 21, 33, 73;
$colors: #fff, #000, #333;
#for $i from 1 through length($ids) {
$id: nth($ids, $i);
$color: nth($colors, $i);
.category--#{$id},
.post--#{$id} {
color: #{$color};
}
}
Hi you misuse it :D #each is iterate list by list see below
$pair: (21, #fff), (33, #000), (73, #333);
#each $id, $color in $pair {
.category-#{$id},
.post-#{$id} {
color: #{$color};
height: 20px;
}
}
doc reference: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#each-multi-assign

Accessing an array key in SASS

I have a list in SASS, and I'm trying to access on of the items by using bracket notation:
$collection[1];
but that gives me an error.
Is there any other way to do this?
Why do I want to do this?
I have a list of colors that have to be set on different elements according to a colors assigned to them by the server. The markup has numbered classes (color-0, color-1, etc.). Here's the CSS I'm aiming for:
.color-0 { color: red }
.color-1 { color: orange }
.color-2 { color: green }
.color-3 { color: blue }
/* many more, with more complex colors... */
Instead of writing it all by hand, I figured I could use a SASS collection with a loop:
$color-collection: ('red', 'orange', 'green', 'blue');
$color-count: length($color-collection);
#for $i from 0 to $color-count {
.color-#{$i} {
color: $color-collection[ $i ];
}
}
but this just gives me the following error:
Syntax error: Invalid CSS after "...color-collection": expected ";", was "[ $i ];"
How can I accomplish this?
$color-collection: ('red', 'orange', 'green', 'blue');
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: unquote(nth($color-collection, $i+1));
}
}
Use nth(), also unquote() if you want to pass quoted strings.
Though, I personally wouldn't:
$color-collection: (red, rgba(50,50,80, .5), darken(green, 50%), rgba(blue, .5));
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: nth($color-collection, $i+1);
}
}
Because then you can pass any color object.
You can use #each rule instead of #for, which is more semantic, faster, and it makes the code shorter:
$color-collection: (red, orange, green, blue);
#each $color in $color-collection {
.color-#{$color} {
color: $color;
}
}
Or if you prefer you can use $color-collection list directly into the #each directive:
#each $color in red, orange, green, blue {
.color-#{$color} {
color: $color;
}
}
As #bookcasey says is preferable to use unquoted strings because then you can pass any color object or function
Sass reference for #each directive
just came across this and tested bookcasey's answer, which works well but I wanted to use the color name as the class instead; I found that this code works as I needed.
$colors: ( 'black', 'white', 'red', 'green', 'blue' );
#for $i from 0 to length($colors) {
$thisColor: unquote(nth($colors, $i+1));
.color-#{$thisColor} {
color: $thisColor;
}
}
using the #{...} allows you to use functions as well, so if you need to use an arbitrary name that may not be used directly in the rules you could use
#for $i from 0 to length($colors) {
.color-#{unquote(nth($colors, $i+1))} {
// some rules that don't actually use the var
// so there's no need to cache the var
}
}
output:
.color-black { color: black; }
.color-white { color: white; }
.color-red { color: red; }
// etc..
Hope this helps someone else!
I had similar problem and tried Alex Guerrero solution. Didn't work form me cause output was like .color-gray:{gray}; instead of .color-1:{gray};.So I modified it a bit and it looks like this:
$color-pallete: (gray, white, red, purple)
$i: 0
#each $color in $color-pallete
.color-#{$i}
color: $color
$i: $i + 1
Oh, ye. I use SASS, not SCSS.

Resources