I have the following array of color definitions:
#colors: ~"black" #000, ~"white" #fff, ~"blue" #008FD6, ~"bluehover" #44A1E0, ~"grayborder" #DBDBDB;
And I use the following function to use those colors within CSS declarations.
.colorkey(#key) {
.-(length(#colors));
.-(#i) when (#i > 0) {.-((#i - 1))}
.-(#i) when (#key = extract(extract(#colors, #i), 1)) {
#colorkey: extract(extract(#colors, #i), 2);
}
.--() {#colorkey: #000} .--;
}
Usage:
.my-div {
.colorkey(~"black");
color: #colorkey
}
However I'd prefer to use the mixin like so:
.colorkey(black);
Without the quotes and tilde. Is it possible to modify the colorkey mixin to achieve this?
If your #colors can be defined without putting the color names in ~"...", you just need to make a minor change:
#colors: black #000, white #fff, blue #008FD6, bluehover #44A1E0, grayborder #DBDBDB;
.colorkey(#key:black) {
.-(length(#colors));
.-(#i) when (#key = extract(extract(#colors, #i), 1)) {
#colorkey: extract(extract(#colors, #i), 2);
}
.-(#i) when (#i > 0) {.-(#i - 1)}
}
.my-div {
.colorkey(bluehover);
color: #colorkey
}
Note that I
removed the extra set of parentheses in your .-(#i) when (#i > 0)
moved that recursive call to the end of .colorkey, and
dropped your .--() {#colorkey: #000} .--; and in its place used .colorkey(#key:black) {. (My guess is that was supposed to make .colorkey; color: #colorkey evaluate to color: #000 but actually it wasn't doing anything :) In the code you provided, to define that default you'd need instead to do .colorkey(#key: ~"black") { )
Related
I have a list of tr elements and I want to add CSS on them with the following pattern :
red
red
red
black
black
black
red
red
red
black
etc.
How can I do this ? for now I've been using :
tr:nth-child(6n+1) { color: red; }
tr:nth-child(6n+2) { color: red; }
tr:nth-child(6n+3) { color: red; }
... but how can I do it with only 1 selector ?
EDIT : Here is a jsfiddle link https://jsfiddle.net/1s5s05vk/2/
I think it will work faster with using css.
.mytable tr:nth-child(6n+1), .mytable tr:nth-child(6n+2), .mytable tr:nth-child(6n+3) {
background-color: red;
}
But if you want, you could use javascript for this.
As I said before.. you could add a class like "red" to any element that has iterator%6 (iterator mod 6) lower than 4.
var rows = document.getElementsByTagName('tr');
for (var i = 0, len = rows.length; i < len; i++){
if(i%6 < 4) {
rows[i].classList.add("red");
}
}
try this. Maybe it can help you.
tr:nth-child(-n+3) {
background: red;
}
tr:nth-child(n+4) {
background: blue;
}
What you want to do cannot be done with a single selector using CSS alone.
However, you can shorten the definition so you don't repeat code:
tr:nth-child(6n+1),
tr:nth-child(6n+2),
tr:nth-child(6n+3) {
color: red;
}
I'm new with Sass stuff and I've been reading about different ways to use variables, this principle I'm trying to apply is just for colors, some of the solutions I've found were something like this (map-get):
$colors: (
lighestGray: #F8F8FA,
lightGray: #A5ACBA,
light: #FFFFFF,
dark: #000000,
link: #428bca,
linkHover: #555,
navBlue: #7AC243,
navGreen: #009CDC,
);
Then you use it on your class like this:
.my-class {
color: map-get($colors, dark);
}
And the other way is to use:
$color-black: #000000;
Then you use it like this:
.my-class {
color: $color-black;
}
My question is, which option is better? or map-getfunction has another purpose?, has Sass a pattern for this or it depends on each web-developer?.
Thanks for helping me out!.
Regards.
The differences is that when you use $map variables, they are best designed for using through iterations or using #each.
Sample case:
SCSS
// Map variable
$icons: (
facebook : "\f0c4",
twitter : "\f0c5",
googleplus : "\f0c6",
youtube : "\f0c7"
);
// Mixin doing the magic
#mixin icons-list($map) {
#each $icon-name, $icon in $map {
#if not map-has-key($map, $icon-name) {
#warn "'#{$icon-name}' is not a valid icon name";
}
#else {
&--#{$icon-name}::before {
content: $icon;
}
}
}
}
// How to use it
.social-link {
background-color: grey;
#include icons-list($icons);
}
CSS
// CSS Output
.social-link {
background-color: grey;
}
.social-link--facebook::before {
content: "";
}
.social-link--twitter::before {
content: "";
}
.social-link--googleplus::before {
content: "";
}
.social-link--youtube::before {
content: "";
}
This code was taken from my own answer in the following post but the answer is a case use of #each :)
Hope this help you
Example making a theme with css variables with fallback color
see codepen css variables
// VARS (FOR FALLBACK)
// -------------------
$theme-base: #70c1ac;
$theme-base-aa: adjust-color($theme-base, $blue: 125);
// PROCESSED THEME
$theme-color: $theme-base;
$theme-color-dark: darken($theme-color, 20%);
$theme-color-light: lighten($theme-color, 20%);
$theme-color-mixed: mix(#fff, $theme-color, 75%);
$theme-color-trans: transparentize($theme-color, .4);
// PROCESSED SECONDARY
$theme-color-aa: $theme-base-aa;
$theme-color-aa-dark: darken($theme-color-aa, 20%);
$theme-color-aa-light: lighten($theme-color-aa, 20%);
$theme-color-aa-mixed: mix(#fff, $theme-color-aa, 75%);
$theme-color-aa-trans: transparentize($theme-color-aa, .4);
$theme-colors: (
"aa-dark": $theme-color-aa-dark,
"aa-light": $theme-color-aa-light,
"aa-mixed": $theme-color-aa-mixed,
"aa-trans": $theme-color-aa-trans,
aa: $theme-color-aa,
dark: $theme-color-dark,
light: $theme-color-light,
mixed: $theme-color-mixed,
theme: $theme-color,
trans: $theme-color-trans,
);
#mixin themeColor ($prop, $color: null) {
#if ($color) {
#{$prop}: map-get($theme-colors, $color);
#{$prop}: var(--theme-color-#{$color})
} #else {
#{$prop}: map-get($theme-colors, theme);
#{$prop}: var(--theme-color);
}
}
#mixin setThemeColors($base1: "", $base2: "") {
// BASE THEME COLORS
$color-base: $theme-base;
$color-aa: $theme-base-aa;
#if ($base1) {
$color-base: $base1;
$color-aa: $base2;
}
// PROCESSED THEME COLORS
$color-aa-dark: darken($color-aa, 20%);
$color-aa-light: lighten($color-aa, 20%);
$color-aa-mixed: mix(#fff, $color-aa, 75%);
$color-aa-trans: transparentize($color-aa, .5);
$color-aa: $color-aa;
$color-dark: darken($color-base, 20%);
$color-light: lighten($color-base, 20%);
$color-mixed: mix(#fff, $color-base, 75%);
$color-trans: transparentize($color-base, .5);
// CSS VARIABLES
--theme-color-aa-dark: #{$color-aa-dark};
--theme-color-aa-light: #{$color-aa-light};
--theme-color-aa-trans: #{$color-aa-trans};
--theme-color-aa: #{$color-aa};
--theme-color-dark: #{$color-dark};
--theme-color-light: #{$color-light};
--theme-color-mixed: #{$color-mixed};
--theme-color-trans: #{$color-trans};
--theme-color: #{$color-base};
}
:root {
#include setThemeColors($theme-base, $theme-base-aa);
}
body {
#include themeColor("background","mixed");
font-size: 2rem;
}
ul {
list-style: none; /* Remove default bullets */
}
ul li::before {
content: "\2022"; /* Add content: \2022 is the CSS Code/unicode for a bullet */
#include themeColor("color","dark");
font-weight: bold; /* If you want it to be bold */
display: inline-block; /* Needed to add space between the bullet and the text */
width: 1.2em; /* Also needed for space (tweak if needed) */
margin-left: -.8em; /* Also needed for space (tweak if needed) */
}
li {
#include themeColor("color", "light");
#include themeColor("background", "aa-dark");
}
Why pick one when you can have them both.
_variables.scss
$color0 : white;
$color1 : red;
$color2 : green;
$color3 : blue;
_lists.scss
#use "variables";
#use "sass:map";
#use "sass:meta";
#use "sass:list";
#function dynamic($variable){
$i: 0;
$list: ();
#while(variable-exists($variable + $i)){
$list: list.append($list, map.get(meta.module-variables(variables), $variable + $i));
$i: $i + 1;
}
#return $list;
}
$colors: dynamic('color'); // white red green blue
Import both into your scss files and use the list when you need to loop and the variables for shorthand when applying styles.
map-get is used for getting css value from more kind of object.
suppose you have $param where you have defined multiple properties and now you want to assign. you can use it in following ways -
color: map-get($params, "color");
Where else simple variable holds only single value
map-get to get css value from object holding multiple values whereas
variable to hold single value
//call the mixin
.mixin-loop(grey, 7);
//the implementation
.mixin-loop(#str, #count) {
.loop (#i) when (#i > 0) {
.#{str}-#{i} {
div { background: "#{#{str}-#{i}}"; }
}
.loop(#i - 1);
}
.loop (#count);
}
//globals.less
#grey-1: #ccc;
#grey-2: #999;
The output I want is this:
//output
.grey-1 div {
background: #ccc;
}
.grey-2 div {
background: #999;
}
But what I'm getting is this:
.#808080-1 div {
background: "#{#808080-1}";
}
.#808080-2 div {
background: "#{#808080-2}";
}
You can use variable interpolation (~) to help with this:
http://lesscss.org/features/#variables-feature-variable-interpolation
This will prevent grey from being converted into it's hex value, and then will allow "#{#{str}-#{i}}" to be displayed as a hex value instead of a string.
//call the mixin
.mixin-loop(~"grey", 2);
//the implementation
.mixin-loop(#str, #count) {
.loop (#i) when (#i > 0) {
.#{str}-#{i} {
div { background: ~"#{#{str}-#{i}}"; }
}
.loop(#i - 1);
}
.loop (#count);
}
//globals.less
#grey-1: #ccc;
#grey-2: #999;
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.
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.