Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SASS : How to generate a map using a loop

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.

like image 759
Vladimir Avatar asked Oct 24 '16 14:10

Vladimir


People also ask

What is a Sass loop?

Sass has several loop options, much like other programming languages. They include the @for loop, @each loop and @while loop. These loops are an incredibly powerful tool for generating CSS code because you can defer code generation into an iterable task.

WHAT ARE FOR loops used for in Sass?

Sass provides us with three different kinds of loops. @for - This loop iterates through a section of code for a set number of times. @while - This loop iterates through a section of code while a condition is true. @each - This loop iterates through all elements in a collection without a condition.

What is @each in Sass?

The @each rule makes it easy to emit styles or evaluate code for each element of a list or each pair in a map. It's great for repetitive styles that only have a few variations between them. It's usually written @each <variable> in <expression> { ... } , where the expression returns a list.

What is map get in SCSS?

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");


1 Answers

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

$colors-map: ();

@function create_colour_map($color, $percentage, $opacity) {
  $map: (
    base: $color,
    light: lighten($color, $percentage),
    dark: darken($color, $percentage),
    trans: transparentize($color, $opacity)
  );
  @return $map;
}

@each $key, $value in $colors {
  $map: ();
  $map: map-merge($map, ($key: create_colour_map($value, 15%, 0.5)) );
  $colors-map: map-merge($colors-map, $map);
}

@debug $colors-map; //prints out the map below 
  (jet:               (base: #333333, 
                       light: #595959,
                       dark: #0d0d0d,
                       trans: rgba(51, 51, 51, 0.5)), 
   wintergreen-dream: (base: #588C73, 
                       light: #81b099,
                       dark: #3a5d4c,
                       trans: rgba(88, 140, 115, 0.5)),
   eton-blue:          (base: #8FC0A9,
                        light: #c0dccf,
                        dark: #5ea483,
                        trans: rgba(143, 192, 169, 0.5)), 
   sunglow:            (base: #FFC33C,
                        light: #ffdb89,
                        dark: #efa500,
                        trans: rgba(255, 195, 60, 0.5)),
   light-kaki:         (base: #F2E394,
                        light: #faf5d8,
                        dark: #ead150,
                        trans: rgba(242, 227, 148, 0.5)),
   bege:               (base: #FAF3DD,
                        light: white,
                        dark: #f0db9a,
                        trans: rgba(250, 243, 221, 0.5)))

I merged your three functions into one, the create_colour_map function. It takes three arguments for the colour, percentage and opacity. The function returns a map

Calling the create_colour_map(#333333, 15%, 0.5) with those args returns a map

(base: #333333, 
 light: #595959,
 dark: #0d0d0d,
 trans: rgba(51, 51, 51, 0.5)
);

I just loop through the $colors map and each time call the function which generates a map that becomes the value of the key each time for an iteration.

How to add values to a map and basic usage of map-merge?

I use map-merge to add values to a map. Just as the name implies, it joins two maps together and since it is a function, it can be used where Sass expects a value. So take for example the code below

$map: ( colour: red);
$new_map: (class: blue);

If we wanted $map to have the same keys and values as both maps, we could write

$map: map-merge( $map, $new_map); // $map: (colour: red, class: blue)

This is basically saying the return value of the function ( which would be the two maps joined together ) is the value of $map

Simply put just think of that line of code as variable reassignment in programming languages. This is how you can use map-merge to set values in maps. The 2nd argument for the map-merge method doesn't need to be a predefined map variable. It could have been written this way

$map: map-merge( $map, (class: blue) );

So here it just looks like you're adding a new key and value to the $map variable

like image 154
Black Enigma Avatar answered Sep 27 '22 03:09

Black Enigma