I am trying to set up a color scheme in SCSS where I can have the following HTML:
<div class="swatch" data-bg="green">...</div>
I have a SCSS mixin defined as such:
@function color($key: 'black') {
@return map-get($colors, $key);
}
So, if I pass it background-color: color('green')
, it will look at the $colors: ( ... )
map, see 'green': #009900,
and return background-color: #009900;
as the CSS.
The problem comes when I try to pass the data-bg
attribute value into the color()
SCSS mixin, like so:
.swatch[data-bg] {
background-color: color(attr(data-bg));
}
This doesn't work. I would expect it to parse the value as such:
color(attr(data-bg))
→ color('green')
→ #009900
However, SCSS won't even render that background-color
line in the CSS at all.
I have a Codepen where you can see what I'm trying to go for. It's the "Brown" color swatch here: https://codepen.io/rbrum/pen/axZLxw
Any help would be greatly appreciated.
For anyone else who happens across this question, here is how I ended up resolving my issue.
Instead of relying on data-
attributes, I just relied on class names instead. Whenever I want an element with a certain background color, for instance, I use a class name like .bg-amber
or .bg-purple
. My colors are defined as such:
$colors: (
'black': #000000,
'white': #FFFFFF,
// ...
'amber': #FFBF00,
'purple': #800080,
// ...
);
To make it easier to access a color, I have defined a function that calls any color by name:
@function c($key: 'black') {
@return map-get($colors, $key);
}
I then define a mixin that, given a color name, will apply it as the background color. I can also pass it a prefix that is used in the CSS attribute.
@mixin bg($color-name, $prefix: '') {
.#{$prefix}#{$color-name} {
background-color: c($color-name);
}
}
If I wanted to use it in a one-off situation, I would use it like so:
@include bg('amber', 'bg-');
...which would generate the following:
.bg-amber {
background-color: #FFBF00;
}
Finally, I use an @each
loop to do this for all of my colors:
@each $color-name, $color-val in $colors {
@include bg($color-name, 'bg-');
}
I can also define a "foreground" version:
@mixin fg($color-name, $prefix: '') {
.#{$prefix}#{$color-name} {
color: c($color-name);
}
}
And then I can use it in the @each
loop right below the bg()
usage:
@each $color-name, $color-val in $colors {
@include bg($color-name, 'bg-');
@include fg($color-name, 'txt-');
}
It can also be extended for things like border colors, box shadows, and more.