I have a scenario where I am using a JSON file in order to dynamically create SASS variables. The plugin (Gulp-json-css) can retain the map and array properties, but does not add quotations onto the map keys:
$palettes : ( white: #ffffff, grey: (lite: #aaaaaa, base: #999999, dark: #666666), black: #000000);
I am running into an issue where map-get() is not able to find the appropriate value if a quoted string is used for the parameter.
map-get($palettes, white) => #ffffff
map-get($palettes, "white") => null
--
Conclusion : (white != "white")
Is there anyway to change a quoted string into an "unquoted" string? I know what you're thinking, but unquote() doesn't work either:
$color : "white";
white == unquote($color) => false
I need a way to turn "white" into white in order to appropriately retrieve the correct value using the map-get() function.
UPDATE / SOLUTION
To whoever comes across this page and is looking for a solution, I ended up writing a function that will loop through a map and add quotes to it's keys:
#function quoteMapKeys( $map )
{
$newMap : ();
#each $key,$value in $map
{
#if type-of($value) == 'map'
{
$value : quoteMapKeys( $value );
}
$newMap : map-merge($newMap, (quote($key):$value));
}
#return $newMap;
}
$palettes : quoteMapKeys( $palettes );
Related
I have two SASS functions that do the same thing, with some differences.
The first function iterates over the map, and then returns a short record so that you can conveniently use the work with color and transparency
// map
$colors: (
primary: #06285c,
seconadary: #96ccff,
tertiary: #357edd,
accent: #ff6300,
info: #a463f2,
success: #19a974,
warning: #ffde37,
danger: hsl(8deg 100% 61%)
);
#function color($key: primary, $opacity: 1) {
#return rgba(map-get($colors, $key), $opacity);
}
// sass style
background-color: color(warning, 0.6);
// compile to
background-color: rgba(255,0,0,.6);
My second function is designed to use whatever color is entered without having to rely on map
#function color-custom($key: primary, $opacity: 1) {
$color: color($key);
#return rgba($color, $opacity);
}
// sass style
background-color: color-custom(#ff0000, 0.6);
// compile to
background-color: rgba(255,0,0,.6);
I would just like to combine both functions into one. I do not know if this is possible, and how to check the dependencies inside the function. At the same time, these functions cannot exist, they give errors. Therefore, I would like to simply unite them, if it is possible.
You can check if $key exists in your map with map-has-key and then set a condition to return the correct result:
#function get-color($key: primary, $opacity: 1) {
$color: if(map-has-key($colors, $key), map-get($colors, $key), $key);
#return rgba($color, $opacity);
}
I've run into an issue where it's easier for me to define two base maps that can be flicked between using a single variable (Seems easier for base, light/dark themes)
https://codepen.io/anon/pen/bLwNaW
I'm trying to set $theme-being-used, check it in a If/Else and use a particular map based on that result.
This makes it simple for me to come in and set $theme-being-used to dark and change all of the base variables.
I've tried:
#if (#{$theme-being-used} == light) {
#if ($theme-being-used == light) {
#if (#{$theme-being-used} == "light") {, etc..
Does anyone know if this can be done? It's not a big deal either way, just saves a little bit of time when throwing up templated sites.
Before I was achieving this by simply comment/uncommenting code, i.e.
$palette: (
// Light
ui: (
primary: #FFFFFF,
secondary: #EEEEEE,
alternate: #DDDDDD
),
// Dark - COMMENTED when I want to use light variables
/*ui: (
primary: #333,
secondary: #444,
alternate: #555
),*/
);
This is fine and pretty quick, but it'd just be easier to set it in one place and not have to do this.
Thanks.
Place $theme-being-used check to _palette function. This function take only one parameter — color name. And contains all color select logic inside itself.
Sassmeister demo.
$theme-being-used: light;
$palette: (
dark: (
primary: red,
secondary: orange,
tertiary: blue
),
light: (
primary: green,
secondary: black,
tertiary: yellow
)
);
#function _palette($color-name, $theme-name: $theme-being-used) {
// Select one of available themes
// Here there may be more complex logic in choosing themes
$theme: map-get($palette, #{$theme-name});
// Get the color from theme
#return map-get($theme, #{$color-name});
}
.s-o {
background: _palette(primary);
&:hover {
background: _palette(secondary);
}
}
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')
}
How can I make the following code more DRY?
I have setup bunch of variables below that are later referenced in a $colors map. Currently I have to edit the code in two places to add a new color to the system. And these variable number will grow in the future considerably.
https://codepen.io/umbriel/pen/LLvPPK
Here is the whole current code section
$red : #cc0000;
$blue : #1e8cea;
$green : #27a249;
$teal : #41bdbb;
$purple : #5c369e;
$-yellow : #ecd340;
#function color-palette($color) {
$map: (
light: scale-color($color, $lightness: 88%),
lighter: adjust-hue(scale-color($color, $lightness: 48%, $saturation: 32%), -8%),
base: $color,
darker: adjust-hue(scale-color($color, $lightness: -36%), 0%),
dark: scale-color($color, $lightness: -72%, $saturation: 100%)
);
#return $map;
}
$colors: (
red: color-palette($red),
blue: color-palette($blue),
green: color-palette($green),
teal: color-palette($teal),
purple: color-palette($purple),
yellow: color-palette($yellow)
);
// retrieve color from map ie. `color(primary, base)`
#function color($color-name, $color-variant:null) {
// color variant is optional
#if ($color-variant != null) {
// map inception
#return map-get(map-get($colors, $color-name), $color-variant);
} #else {
#return map-get(map-get($colors, $color-name), base);
}
}
I have tried looping the map inside the $colors map which didn't work.
$colorvars : (
red : #cc0000,
blue : #1e8cea,
green : #27a249,
teal : #41bdbb,
purple : #5c369e,
yellow : #ecd340
)
$colors: (
#each $key, $value in $colorsvars {
$key : color-palette($value)
}
)
DRY adding colors (and its variations):
There's an excellent article that describe how to do it better than I could ever explain. Basically you create a list of colors, then list of variations that contains what function should be applied to modify color and parameters for that function. Finally you kind of create an interface/one simple to use function for getting final color value. The important thing is that all colors and possible variations are declared in one place.
DRY generating selectors:
Another thing you might consider is the way to generate all these selectors. You could use #each directive to go through all colors and variations and generate all selectors/classes in 1 place. Something like:
#each $color in $colors {
#each $variation in $variations {
.c-#{$color}-#{$variation} {
background-color: a-nice-function-to-get-color($color, $variation);
}
}
}
However, this usually isn't such a great idea, as it makes searching selectors in your IDE way harder. If you're really going to have so many different colors, then it might be worth thinking about using this technique, though.
I'm trying to generate a rather automated system to define colours in SASS. I have a list of colours, defined with a hexidecimal value (like so: $color--deep-ocean: #123143;) and a global $colors: (); definition.
I then want to create their RGBA values dynamically, and given variable interpolation isn't an option in SASS, I've tried my hands at maps.
The idea is to feed a set-color function a name and a color to populate my $colors variable with map-merge, which I can then retrieve with get-color. Here below are my two function definitions and how I'm trying to use them:
#function color-set($name, $hex) {
$submap: (hex: $hex);
#for $o from 0 to 20 { // Going in increments of 5
$percentage-decimal: $o*0.05;
$percentage: $o*5;
$submap: map-merge($submap, ($percentage: rgba($hex, $percentage-decimal)));
}
$colors: map-merge($colors, ($name: $submap));
/* We should then have a map that looks like this:
$colors: (colorname: (
hex: #000000,
0: rgba(0,0,0,0),
5: rgba(0,0,0,.05),
// and so on…
100: rgba(0,0,0,1)
)
)
… right? */
}
#function color-get($name, $opacity: hex) {
#if $opacity != hex { // Returns RGBA value
#return map-get(map-get($colors,$name), $opacity);
}
#else { // Returns hexidecimal value
#return map-get(map-get($colors,$name), hex);
}
}
Please let me know if my functions are confusing! I'll try to comment them better.
This is how I'm trying to define a colour (part of _variables.scss):
color-set(bkgrnd, $color--deep-ocean);
And here's how I'm trying to use my colours:
body { // These colours have been defined, too …supposedly
background-color: color-get(bkgrnd, 80);
color: color-get(white);
}
Here is the error I get on _variables.scss:
Invalid CSS after "...ackground color": expected 1 selector or at-rule, was "color-set(bkgrnd, $"
So I feel like I'm missing something. I've had my head wrapped around this for four hours and I'm going mad. It's probably super simple stuff but I can't seem to figure it out. I use SASS casually, so I might not be aware of some syntax issue but if anyone has a clue about how to fix this, I'd be quite grateful.
Have a nice day and thank you for taking the time to read my post!
Regards,
Chris
PS: I compile this in Brackets with the Brackets SASS plugin, if ever that information is relevant.
After digging some more, I found out what my issue was. SASS functions must have a #return directive in order to work. As a result, I updated my color-set function, and added #return $colors; at the end of it. Then, I just needed to give some directive so the function wouldn't be called "out of the blue", so I assigned my $colors variable to it like such:
$colors: color-set(bkgrnd, $color--deep-ocean);
I think it might be a bit repetitive to reassign $colors to itself all the time, but given this only affects performance during compilation, and not on my final CSS file, I can get away with it. There might be a better way (and I'm all ears if you have an idea!) but for now this fits my needs just fine.
And like that, I am able to handle my colors using maps. Thanks to anyone who had a look at my problem, and sorry for posting this - I should have taken some time to cool down and think some more. I hope this helps someone else who is stumbling on the same problem to fix their issues!
Take care,
Chris
PS: If ever you wanted it, below is the full code.
_colors.scss
$color--deep-ocean: #123143;
$color--yellow: #ffce00;
// And so on, and so forth…
_mixins.scss
#function color-set($name, $hexval) {
#return map-merge($colors, ($name: $hexval));
}
#function color-get($name, $opacity: hex) {
#if $opacity != hex { // Returns RGBA value
$opacity-decimal: $opacity/100;
#return rgba(map-get($colors,$name), $opacity-decimal);
}
#else { // Returns hexidecimal value
#return map-get($colors, $name);
}
}
_variables.scss
$colors: color-set(bkgrnd, $color--deep-ocean);
$colors: color-set(main, $color--yellow);
// And so on, and so forth again…
Usage example:
body {
background-color: color-get(bkgrnd); // Returns #123143
color: color-get(main); // Returns #ffce00
}
button {
border: 2px solid color-get(main, 50); // Returns rgba(255, 206, 0, 0.5)
}