Make Rainbow-Colored Lists (and other HTML elements) – jQuery plugin
How to make rainbow-colored lists? I started searching for a solution and found a plugin for rainbow text, which inspired me to write my own jQuery plugin to rainbow-ify lists and other sets of HTML elements.
I’m used to working with RGB hex color codes. But there is no intuitive way to generate a spectrum of color using RGB, so I turned to HSL (hue, saturation and lightness). Most modern browsers support colors specified with hsl(hue, saturation%, lightness%)
, although IE versions prior to 9 do not. So I started out using HSL, adding IE support later. I found that keeping the saturation and lightness constant at 100% and 80% respectively while increasing the hue in steps produces a really nice rainbow effect.
Let’s back up a bit. Consider the following styled list:
I’d like to color this list to look like a rainbow. Using CSS alone is unwieldy; without knowing in advance the number of elements in the list, it’s impossible. We need to use Javascript to get this result:
Here’s how I did it–my rainbow plugin code (~1KB when minified):
(function($) { 'use strict'; //the plugin function $.rainbow = $.fn.rainbow = function(options) { if (this.length !== 0) { //initialize settings & vars var settings = $.extend( { hueStart: 0, selector: '> *', saturation: 100, lightness: 80, rgb: true }, options), $rainbowed = this, //ensure values are within proper range hstart = ensure(settings.hueStart, 0, Number.MAX_VALUE) % 360, sat = ensure(settings.saturation, 0, 100), light = ensure(settings.lightness, 0, 100); return $rainbowed.each(function() { var $selected = $(this).find(settings.selector), hue = hstart, step = $selected.length === 0 ? 0 : 360 / ($selected.length); // iterate over selected elements to colorize $selected.each(function() { if (!settings.rgb) { $(this).css({'background-color': 'hsl('+ hue +', '+ sat +'%, '+ light +'%)', 'border-color': 'hsl('+ hue +', '+ (sat / 2) +'%, '+ (light / 2) +'%)'}); } else { $(this).css({'background-color': hslToRgb(hue, sat, light), 'border-color': hslToRgb(hue, sat / 2 , light / 2)}); } hue += step; }); }); } }; function ensure(val, min, max) { val = parseInt(val, 10); if (isNaN(val) || val < min) return min; else if (val > max) return max; else return val; } function hslToRgb(h, s, l) { var r, g, b; h = h / 360; s = s / 100; l = l / 100; if (s === 0) r = g = b = l; // achromatic else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return 'rgb('+ Math.round(r * 255) +','+ Math.round(g * 255) +','+ Math.round(b * 255) +')'; } function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; } })(jQuery);
This plugin accepts several optional arguments:
- hueStart – a value from 0 to 360 representing the start of the rainbow, defaulted to 0 which is red.
- selector – a jQuery selector that grabs the set of elements to colorize, defaulted to “> *”, i.e. all children.
- saturation – a value from 0 to 100 representing the saturation percentage, defaulted to 100.
- lightness – a value from 0 to 100 representing the lightness percentage, defaulted to 80.
- rgb – a boolean value instructing the plugin to use CSS RGB syntax instead of HSL, defaulted to true.
Note that rgb = true requires some additional overhead to convert HSL to RGB, but is necessary if you are supporting IE versions prior to 9. Credit for the conversion function goes to Mohsen @ SO.
This is the HTML for the list:
<ul id="rainbowList"> <li>Java</li> <li>JavaScript</li> <li>PHP</li> <li>Python</li> <li>C#</li> <li>C++</li> <li>SQL</li> <li>Objective-C</li> <li>Visual Basic</li> <li>Ruby on Rails</li> <li>Scala</li> <li>jQuery</li> <li>HTML5</li> </ul>
The initial CSS:
#rainbowList { list-style: none; width: 270px; margin: 10px; } #rainbowList li { background-color: #ddd; border: 1px solid #999; border-radius: 3px 3px 3px 3px; color: #333; padding: 3px 7px; text-align: center; text-decoration: none; width: 200px; font: bold 1em Georgia,serif; margin: 6px; }
And calling the plugin to turn it from gray to rainbow:
$(document).ready(function() { $('#rainbowList').rainbow(); });
Notice in this example I’m using all the plugin defaults. The rainbow colors are applied to the li
tags. The number of rainbowized elements can be arbitrary; the plugin will step through the color spectrum with a finer or coarser grain depending on how many elements there are. Note as well that there is no requirement to use a list. Any HTML structure can be used.
The result here looks good, but it’s not quite good enough. Some CSS shadowing effects will make it pop, so I added this to the li’s style:
box-shadow: 1px 1px 1px 1px rgba(255, 255, 255, 0.5) inset, -1px -1px 1px 0 rgba(0, 0, 0, 0.3) inset, 1px 1px 1px 1px rgba(33, 33, 33, 0.14); text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.5);
That’s three box shadows for each li
tag. The first adds a light inner shine from the upper left, the second adds a bit of an inner shadow on the bottom right, and the last adds a subtle drop shadow. I included a text shadow as well. This is the final result:
Try the demo to adjust the rainbow plugin settings and view the results. You can play around with the starting hue, the saturation and lightness.
I hope you find this plugin useful! Feel free to use it in your projects. A link back here is not required, but always appreciated!