5

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.

TerranRich
  • 1,263
  • 3
  • 20
  • 38
  • 3
    SASS is precompiled so you can't use runtime variables. – James Coyle Apr 11 '19 at 15:28
  • You can still use `attr()`, you'll just have to omit the SASS-specific `color()` and make sure that the contents of the attribute are valid color notations in CSS. – Constantin Groß Apr 11 '19 at 15:52
  • Since that is true, @JamesCoyle, I guess all I can hope for is a SASS function/mixin that takes in a string, and call it with each color name. E.g. `@include generate-bg-color('brown');`, etc. – TerranRich Apr 15 '19 at 22:56
  • Actually, I've written an `@each` loop that iterates through each color in the map, then generates the background colors that way. This way, I can just have `class="swatch green"`, and in my SASS I can apply styling to each color class. – TerranRich Apr 16 '19 at 15:54

1 Answers1

3

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.

TerranRich
  • 1,263
  • 3
  • 20
  • 38