This is a collection of SASS snippets that I like to use to generate a light to dark shades/tints from a color pallette. It's complete overkill for small applications, but for applications that look to incorporate imagery and animations these. I based this off of different articles and techniques I've read, primarily: Using a Sass map for colors.

The Basics

First create a map of all the base colors:

$colors: ( "primary": #eaeb24, "purple": #8824eb, "blue": #2524eb, "green": #24eb88, "cyan": #d43e7c, "lilac": #5d59a6, );
undefined

Then we can generate a map of all our color shades. I like to emulate how light effects colors in the real world, with colors under shadows becoming desaturated. I also like to have color names match up with how they are named in design software. Since I'm using Figma, color names follow the pattern of Red 50:

@function color-map($color, $values) { $base: $values; $lightest: scale-color(mix(#fff, $values, 60%), $saturation: 13%); $lighter: scale-color(mix(#fff, $values, 25%), $saturation: 11%); $darker: scale-color(mix(#000, $values, 30%), $saturation: -9%); $darkest: scale-color(mix(#000, $values, 45%), $saturation: -15%); $color-shades: ( #{$color}-100: $lightest, #{$color}-75: $lighter, #{$color}-50: $base, #{$color}-25: $darker, #{$color}-0: $darkest ); @return $color-shades; }
undefined

Now prepare a map that we can easily loop through to generate styles like background-color:

// Setup the map for all colors @function color-maps($colors) { $color-map: (); @each $color, $value in $colors { $map: (color-map($color, $value)); $color-map: map-merge($color-map, $map); } @return $color-map; } // Now build that map $color-map: color-maps($colors);
undefined

Finally, the exciting part, generating helper classes:

@each $name, $color-shade in $color-map { .background-#{$name} { background-color: #{$color-shade}!important; }; .text-#{$name} { color: #{$color-shade}!important; }; .border-#{$name} { border-width: 1px; border-style: solid; border-color: #{$color-shade}!important; }; }
undefined

Using CSS Varialbes Instead of a SASS Map

I'm not a fan of calling a map everytime I want to use a color. It's also not easily possible to call on a SASS map from within components when using a framework like Svelte or Vue.

Let's create a mixin for dumping the contents of a SASS Map out as a global CSS variables:

@mixin dump-map($map) { :root { @each $name, $value in $map { --#{$name}: #{$value} } } }
undefined

Then call whatever maps we want to dump as CSS Variables:

@include dump-map($color-map); @include dump-map($colors); @include dump-map($deliberate-colors); @include dump-map($white-opacity);
undefined

And the result is the following in our CSS:

:root { --primary-100: #f8f8a6; --primary-75: #f1f259; --primary-50: #eaeB24; --primary-25: #9e9f1f; --primary-0: #79791c; --purple-100: #cfa6f8; --purple-75: #a659f2; --purple-50: #8824eb; --purple-25: #5f1f9f; --purple-0: #4b1c79; --blue-100: #a7a6f8; --blue-75: #5a59f2; --blue-50: #2524eb; --blue-25: #201f9f; --blue-0: #1c1c79; --green-100: #a6f8cf; --green-75: #59f2a6; --green-50: #24EB88; --green-25: #1f9f5f; --green-0: #1c794b; --cyan-100: #f0b0cb; --cyan-75: #e36a9c; --cyan-50: #d43e7c; --cyan-25: #8f3058; --cyan-0: #6f2845; --lilac-100: #bab8e0; --lilac-75: #7f7cc3; --lilac-50: #5D59A6; --lilac-25: #434072; --lilac-0: #363458; }
undefined

Dealing with Exceptions

There is a flaw to generatinig colors alogrithmically instead of by hand. We perceive a color like Yellow as being brighter than a color like Blue. I also run into issues with black, white and gray as the shading is either too dramatic, or not dramatic enough.

For this site, I used seperate SASS Maps and typed out those colors:

$white: #FAFAFA; $black-0: #13130E; $black-25: #232210; $gray-50: #808080; $gray-25: #6E6D69; $primary-00: #403F17; $text: #484848; $deliberate-colors: ( "white": $white, "black-0": $black-0, "black-25": $black-25, "gray-50": $gray-50, "gray-25": $gray-25, "primary-00": $primary-00, "text": $text, ); $white-opacity: ( "white-opacity-90": rgba($white, .9), "white-opacity-75": rgba($white, .75), )
undefined

Alternatively, adding if statements when generating the color map is another way to introduce either additional colors, or different mapping altogether:

@function color-map($color, $values) { $base: $values; $lightest-ssjgssj: scale-color(mix(#fff, $values, 99%), $saturation: 21%); $lightest-ssjg: scale-color(mix(#fff, $values, 97%), $saturation: 19%); $lightest-ssj3: scale-color(mix(#fff, $values, 93%), $saturation: 18%); $lightest-ssj2: scale-color(mix(#fff, $values, 90%), $saturation: 17%); $lightest-ssj: scale-color(mix(#fff, $values, 80%), $saturation: 15%); $lightest: scale-color(mix(#fff, $values, 60%), $saturation: 13%); $lighter: scale-color(mix(#fff, $values, 25%), $saturation: 11%); $light-hint: scale-color(mix(#fff, $values, 15%), $saturation: 9%); $dark-hint: scale-color(mix(#000, $values, 5%), $saturation: -3%); $darker: scale-color(mix(#000, $values, 30%), $saturation: -9%); $darkest: scale-color(mix(#000, $values, 45%), $saturation:-15%); $color-shades: ( #{$color}-100: $lightest, #{$color}-75: $lighter, #{$color}-66: $light-hint, #{$color}-50: $base, #{$color}-33: $dark-hint, #{$color}-25: $darker, #{$color}-0: $darkest ); @if $color == "goku" or "vegita" { $map: (#{$color}-200: $lightest-ssj); $color-shades: map-merge($color-shades, $map); } @if $color == "goku" { $map: (#{$color}-300: $lightest-ssj2); $color-shades: map-merge($color-shades, $map); } @if $color == "goku" { $map: (#{$color}-400: $lightest-ssj3); $color-shades: map-merge($color-shades, $map); } @if $color == "goku" { $map: (#{$color}-500: $lightest-ssjg); $color-shades: map-merge($color-shades, $map); } @if $color == "goku" { $map: (#{$color}-600: $lightest-ssjgssj); $color-shades: map-merge($color-shades, $map); } ITS OVER 9000 @if $color == "goku" { $map: (#{$color}-9001: $lightest-perfectultrainstinct); $color-shades: map-merge($color-shades, $map); } @return $color-shades; }
undefined

I tend to prefer creating static SASS Maps instead of polluting the main function with conditional statements. When a given color has been identified as needing to be hand tuned, then it's variants will likely need to be hand typed anyways.

But Why Though?

To save time. These snippets generate a lot of helper classes without having to type them by hand. I also find that helper classes prevent CSS spaghetti and cut down on front end development time substantially.

To establish a consistent palette of colors. I've seen numerous times the need for shades and tints for elements like alert boxes, CTA buttons and vector images. Shadows and grayscale elements also tend to deviate wildly as not all branding guides include shades of gray. Generated colors are also sent back to the design team. It's also trivial to adjust colors when they're all located in the same place in the code and called from variables.