Using SASS to generate colors dynamically.

I’m fairly new to SASS. To try to get my head around it, I wondered: could I use SASS to dynamically create an array of colors blocks, starting with only a base color?

First step: search. I read up on SASS color functions used to measure lightness, or to adjust a base color by lightening, darkening, hue, or complement. I found the docs for SASS loops, but I still couldn’t quite grok how to put it all together.

Finally, I turned up ANT1n’s great codepen demo, which basically did, well, just what I wanted. So I took a closer look, added a few more variables, and a few different arithmetic methods to increment the color variations.

Here’s the Pen I put together:

See the Pen dynamic color generation with SASS by Matthew Pinto (@openstatues) on CodePen.

How it all works:

First, some very simple markup. A ten-item list:

<h2>Multiplicative Hue</h2>
<ul class="multiplicative hue">
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
 <li class="button"></li>
</ul>

Nothing too fancy there. Next, the SASS.

First, we create a few variables so we can easily tweak our color settings down the road:

/* set a base color, any color you like */
$base-color: rgb(239, 109, 172);

/* how many units do you want to loop through? can't exceed max number of elements in the child group */
$gradiated-buttons-count: 10; 

/*  Adjust this number to increase or decrease the strength of the color function */
$strength: 5; 

Now, for our loop. We’ll show the “multiplicative darken” method here:

@for $i from 0 to $gradiated-buttons-count {
      ul.multiplicative .button:nth-child(#{$i}) {
      background-color: darken($base-color, $i*$strength);
    }
  }

Let’s unpack this:

We create a “for” loop, which will do whatever we tell it to do FOR each item inside the brackets.

@for

Then we set a range for the loop to work on.

$i from 0 to $gradiated-buttons-count

In this case we use the shorthand variable $i to incrementally pass through the range from 0 (the first item) to the $gradiated-buttons-count variable, which is set to 10, conveniently equal to the numbers in the list. (As you’ll see in the Postscript, below, I really wanted to figure out a way to make that range dynamic, but alas, I could not. Javascript or other wizardry needed there.)

Now, what are we going to do as we loop through the range we’ve defined?

First, define which element we’ll be modifying:

ul.multiplicative .button

Ok, we’re going to be looping through all <li> elements with the “button” class that are descendants of the <ul> with “multiplicative” class. Then, we get a little sneaky. We use the :nth-child pseudo element to incrementally set a different value on each subsequent item!

.button:nth-child(#{$i})

Now we’ve got our differentiation via increments, we can use SASS color functions to define what colors we’ll fill each li.button with. In this case, we’ll use darken(), and fill that with the $base-color variable we set up top (this can be any typical CSS friendly color value).

background-color: darken($base-color, $strength);

But that will still set the same background color to each <li>. We have to dynamically increment what I’m calling the ‘strength’ argument to get ourselves up the mountain:

background-color: darken($base-color, $i*$strength);

What we do here is use our handy increment variable, $i, and then multiply it by our $strength variable (currently set to 5)–this means that as we loop through our range, the color will darken first by (0*5)=0, then by (1*5)=5, then by (2*5)=10, and so on.

The next three variations simply tweak that strength equation.

We can get a more subtle variation by adding instead of multiplying:

$i+$strength

Or we can get a dramatic variation by removing the strength variable and exponentially multiplying:

$i*$i

Finally, for fun, I added three more lists, and instead of
darken(), used adjust-hue. Again we applied the additive, multiplicative, and exponential ‘strength’ equations as arguments, and then introduced a fourth, setting up a variable for $degrees, by which the hue may be further adjusted. We multiply $degrees by the increment variable, and the colors spin out accordingly.

One interesting note here, since there are 360 degrees in the color wheel, if we set the $degrees variable to 120, the colors repeat every 3 iterations, as the wheel comes full circle.


Postscript: As mentioned above, I’d really hoped to figure out a way to do this without needing to know the number of items in the list, but this proved (to my knowledge) impossible, because SASS cannot read the DOM (ie, there’s no way for the SASS to know how many items are before it does it’s compiling to the stylesheet, which then renders the items). Please let me know if there’s a way to do this!