Last Updated
Viewed 02 Times
        

I am trying to find the most efficient way to output multiple color values from a function. The function (will eventually) take the base color and output a color scheme using sass functions (think complementary, tertiary, monochromatic, etc...).

Here is my code that produces the error

background-color: #020633, color:b7bced Isn't a valid CSS value

I'm sure that I need to replace the comma with a semicolon, I'm just not sure if I can or if I'm going about this properly.

$base-color: #0a104e;

@function darkest-color($darkest-base-color-bg) {
    //figure the backgound
    $darkest-bg-color: scale-color($darkest-base-color-bg, $saturation: 66%, $lightness: -40%, $alpha: 100%);
    //figure the text
    $darkest-text-color-nocontrast: scale-color($darkest-base-color-bg, $saturation: 66%, $lightness: 40%, $alpha: 100%);
    //figure the contrast between the background and the text
    $darkest-text-color: color_adjust_contrast_AERT($darkest-text-color-nocontrast, $darkest-base-color-bg);
    //add the two colors to a map
    $darkest-color: '';
    @return $darkest-color (background-color: $darkest-bg-color, color:$darkest-text-color, );
}

.darkest-accent-strip {
    content: darkest-color($base-color);
}

I'm trying to dynamically create my color palettes from a set of base colors using SASS. I was previously creating each base color manually by first defining a set of color variables, then creating a map of each base color with various shades. Then every color map was put into a palette map.

Then to return a color/shade I would use a function which retrieved the value from the color map within the palette map.

It was so long winded, not to mention annoying whenever I wanted to add another color, so I wanted to try and do this dynamically but I seem to be having a bit of trouble with creating a map using a variable name, as far as I can tell.

Here is my previous code just to give you an idea of what I was doing:

$color-percent-change: 3%;

$color-blue: hsla(196, 85%, 57%, 1);
$color-brown: hsla(15, 40%, 33%, 1);
$color-charcoal: hsla(0, 0%, 23%, 1);

$blue: (
    'lighten-3': lighten($color-blue, ($color-percent-change * 3)),
    'lighten-2': lighten($color-blue, ($color-percent-change * 2)),
    'lighten-1': lighten($color-blue, ($color-percent-change * 1)),
    'base': $color-blue,
    'darken-1': darken($color-blue, ($color-percent-change * 1)),
    'darken-2': darken($color-blue, ($color-percent-change * 2)),
    'darken-3': darken($color-blue, ($color-percent-change * 3))
);

$brown: (
    'lighten-3': lighten($color-brown, ($color-percent-change * 3)),
    'lighten-2': lighten($color-brown, ($color-percent-change * 2)),
    'lighten-1': lighten($color-brown, ($color-percent-change * 1)),
    'base': $color-brown,
    'darken-1': darken($color-brown, ($color-percent-change * 1)),
    'darken-2': darken($color-brown, ($color-percent-change * 2)),
    'darken-3': darken($color-brown, ($color-percent-change * 3))
);

$charcoal: (
    'lighten-3': lighten($color-charcoal, ($color-percent-change * 3)),
    'lighten-2': lighten($color-charcoal, ($color-percent-change * 2)),
    'lighten-1': lighten($color-charcoal, ($color-percent-change * 1)),
    'base': $color-charcoal,
    'darken-1': darken($color-charcoal, ($color-percent-change * 1)),
    'darken-2': darken($color-charcoal, ($color-percent-change * 2)),
    'darken-3': darken($color-charcoal, ($color-percent-change * 3))
);

$palette: (
    'blue': $blue,
    'brown': $brown,
    'charcoal': $charcoal,
);

@function color($color, $type: 'base') {

    @if map-has-key($palette, $color) {

        $current: map-get($palette, $color);

        @if map-has-key($current, $type) {

            @return map-get($current, $type);

        }
    }

    @warn 'Unknown #{$color} - #{$type} in #{$palette}.';
    @return null;

}

.blue {
    color: color('blue', 'lighten-2');
}

jsfiddle

So now I'm creating a colors map with each color name/value, then looping through each key in the map and dynamically creating the base colors shade palette and using a similar function to return the color value, but I'm getting the error:

argument `$map` of `map-has-key($map, $key)` must be a map

Here is the new code:

$color-percent-change: 3%;

$colors: (
    'brand': hsla(265, 35%, 50%, 1),
    'black': hsla(0, 0%, 0%, 1),
    'blue': hsla(196, 85%, 57%, 1),
    'brown': hsla(15, 40%, 33%, 1),
    'charcoal': hsla(0, 0%, 23%, 1),
    'emerald': hsla(140, 52%, 55%, 1),
    'green': hsla(101, 55%, 60%, 1),
    'grey': hsla(0, 0%, 47%, 1),
    'indigo': hsla(225, 57%, 47%, 1),
    'orange': hsla(34, 100%, 53%, 1),
    'pink': hsla(309, 80%, 70%, 1),
    'purple': hsla(285, 67%, 60%, 1),
    'red': hsla(11, 85%, 57%, 1),
    'silver': hsla(0, 0%, 80%, 1),
    'slate': hsla(210, 20%, 33%, 1),
    'teal': hsla(180, 100%, 24%, 1),
    'white': hsla(0, 100%, 100%, 1),
    'yellow': hsla(55, 100%, 57%, 1),
);

@each $name, $color in $colors {
  $name: (
    'lighten-10': lighten($color, ($color-percent-change * 10)),
    'lighten-9': lighten($color, ($color-percent-change * 9)),
    'lighten-8': lighten($color, ($color-percent-change * 8)),
    'lighten-7': lighten($color, ($color-percent-change * 7)),
    'lighten-6': lighten($color, ($color-percent-change * 6)),
    'lighten-5': lighten($color, ($color-percent-change * 5)),
    'lighten-4': lighten($color, ($color-percent-change * 4)),
    'lighten-3': lighten($color, ($color-percent-change * 3)),
    'lighten-2': lighten($color, ($color-percent-change * 2)),
    'lighten-1': lighten($color, ($color-percent-change * 1)),
    'base': $color,
    'darken-1': darken($color, ($color-percent-change * 1)),
    'darken-2': darken($color, ($color-percent-change * 2)),
    'darken-3': darken($color, ($color-percent-change * 3)),
    'darken-4': darken($color, ($color-percent-change * 4)),
    'darken-5': darken($color, ($color-percent-change * 5)),
    'darken-6': darken($color, ($color-percent-change * 6)),
    'darken-7': darken($color, ($color-percent-change * 7)),
    'darken-8': darken($color, ($color-percent-change * 8)),
    'darken-9': darken($color, ($color-percent-change * 9)),
    'darken-10': darken($color, ($color-percent-change * 10))
  );
}

@function color($color, $type: 'base') {
    @if map-has-key($color, $type) {
        @return map-get($color, $type);
    }
    @warn 'Unknown #{$color} - #{$type} in #{$color}.';
    @return null;
}

.red {
    color: color('red', 'lighten-2');
}

jsfiddle

I think that the @each loop defining $name as a variable name is causing a problem as it's not recognizing it as a SASS map? But I'm not completely sure, usually my SASS files are pretty simple, this is the first time I've really gone further than just using simple variables and functions with it, so I'm probably missing something relatively straight forward?

I am trying to create a get-ancestors() function that takes a $key and returns all ancestors in a list like this:

$ancestors-map : (
    'button' : (),
     'small-button' : (
            'button'
    ),
    'hollow-button' : (
            'button',
    ),
    'small-hollow-button' : (
            'small-button',
            'hollow-button',
    )
);

Calling get-ancestors('small-hollow-button') should return ('small-button', 'button', 'hollow-button', 'button')

I would like to then remove duplicated ancestors, but I should be able to figure that out. Any help would be much appreciated.

Edit: I have tried many things, and the closest I got was with something like this:

@function get-ancestors($ancestors, $key) {
    $value: map-get($ancestors-map, $key);

    @if length($value) == 0 {
        @return $ancestors;
    }

    @each $ancestor in $value {
        @return get-parents($ancestors, $ancestor);
    }    
}

Edit: Thanks for the answer, here's my final setup with an expanded example:

$ancestors: (
    'red' : (),
    'background-color' : ('red'),
    'button' : (),
    'red-bg' : ('background-color'),
    'small-button' : ('button'),
    'hollow-red-button' : ('button', 'red-bg'),
    'small-hollow-red-button' : ('small-button', 'hollow-red-button')
);

@function get-ancestors($key, $list: ()) {
  $key-list: map-get($ancestors, $key);

  @if length($key-list) == 0 { 
    $list: join($list, $key)
  } @else {
    @each $parent in $key-list {
      $list: get-ancestors($parent, $list);
    }
    $list: join($list, $key)
  }

  @return $list;
}

.cool {
  content: get-ancestors($key: 'small-hollow-red-button');
}

My goal is to generate a SASS map to store variants of colors that are stored in the following map:

  $colors : (

    jet                 : #333333,
    wintergreen-dream   : #588C73,
    eton-blue           : #8FC0A9,
    sunglow             : #FFC33C,
    light-kaki          : #F2E394,
    bege                : #FAF3DD

  );

So far, I am using a @function to retrieve these variants:

  @function light       ($color, $val) { @return lighten($color, $val);     }
  @function dark        ($color, $val) { @return darken($color, $val);      }
  @function transparent ($color, $val) { @return transparent($color, $val); }


The map I am expecting to be able to generate would look alike the following:

  $colors-map : (

    eton-blue : (

        base  : $eton-blue,
        light : lighten($eton-blue, 15%),
        dark  : darken($eton-blue, 15%),
        trans : transparent($eton-blue, .5)


    ),

    jet : (

      base  : $jet,
      light : lighten($jet, 15%),
      dark  : darken($jet, 15%),
      trans : transparent($jet, .5)

    )

    // ...

  );


Yet, the loop I've already tried to apply, looks like this:

@for $key, $value in $colors {}

However, I was naive to believe it could work inside of the map itself.


Questions which answers could easier answer this doubt :

  • How to add values to a SASS map (function), (key:value) ?
  • Basic usage of map-merge/map-set ? (@return map-merge($map, $new))

Strictly what I am looking for below :

$alternative-colors : (

    @each $color, $hex in $colors {

        #{$color} : (

            light : lighten($color, 25%),
            dark  : darken($color, 25%)

        );

    }

);

But yet, it returns following error:

Error: Invalid CSS after \"...tive-colors : (\": expected \")\", was \"@each (...)

Conclusion

Long time have passed, and I it would be nice if I could share my solution with everyone else.

I have created a repo to store the results of this problem solving, https://github.com/vladimirlisovets/SASS-Color-Palettes.

Hope it to be useful to someone either to inspire for something better.

Cheers.

Similar Question 4 (1 solutions) : Auto generated sass maps

Similar Question 5 (1 solutions) : Loop through nested SASS Maps to create classes

Similar Question 6 (1 solutions) : SCSS/SASS get values from nth nested maps

Similar Question 7 (2 solutions) : How can an empty Map be created in Sass?

Similar Question 8 (1 solutions) : Creating values in SASS map for modular scale ms-range

cc