Generating random colors


My web color scheme generator is currently set up to reflect my own biases. The results are almost always readable, even for people with various forms of color-blindness, but who’s to say that my way is best?

Well, me, of course, but once or twice a year I’m willing to admit that I might be wrong about something. In recognition of that possibility, I’ll explain the syntax for the mini-language I created for the generator.


Let’s start with the default ruleset:

base: r=[0,100]; g=[0,100]; b=[0,100]
back: base; h+[-15,15]; s=[0,10]; v=[90,100]
side: base; h+[-90,90]; v=[75,85]
text: base; h+[-30,30]; s=[90,100]; v=[0,20]
head: back,side; s=[90,100]; v=[20,50]
link: back,side,text; s=100; v=40
visited: link; v-10

The format is “label: operation [; operation …]”; that is, a name for the color that’s being generated, followed by one or more color changes, processed left to right. A simple, self-contained rule would be something like “green: #00ff00”, which would define the color named green to be, well, green.

Rules can refer to previously-generated colors by name, copying them and then modifying one or more color channels: “yellow: green; r=100”. Additional colors in a rule are linearly interpolated with the current color. If I had defined red to be #ff0000, then the color produced by the rule “red,green” would be #7f7f00, which is definitely not yellow. Adding colors rather than interpolating them would be interesting, but I haven’t implemented it yet because I think interpolation is more useful for creating contrast on a web page.

That’s why I defined yellow to be a copy of green with the “r” channel set to 100%, which is my sneaky way of introducing channel operations. Six different channels are supported, representing the RGB (red, green, blue) and HSV (hue, saturation, value) color spaces. Hue can be modified in a range from -360 to 360 degrees, while the others range from 0 to 100%. They are of course represented by the variables r, g, b, h, s, and v.

You can do three things to a channel: set its value to some number (=), add to its current value (+), and subtract from its current value (-). This number can be selected randomly from a range, such as “r+[30,60]”, which adds a number between 30 and 60 to the red channel. If the result of the operation is too big or too small, it’s automatically set to the nearest valid number.

With that in mind, the default ruleset (loosely based on one in Kasper J. Jeppesen’s ColorDesigner Mac application) breaks down as follows:

  1. base: set r, g, and b to random values.
  2. back: copy base, then rotate the hue between -15 and 15 degrees, set the saturation to between 0 and 10%, and set the value (brightness) to between 90 and 100%. (very light, low-saturation background)
  3. side: copy base, then rotate the hue between -90 and 90 degrees, and set the value between 75 and 85%. (fairly light sidebar)
  4. text: copy base, then rotate the hue between -30 and 30 degrees, set the saturation between 90 and 100%, and set the value between 0 and 20%. (very dark, saturated text color)
  5. head: Interpolate between back and side, then set the saturation between 90 and 100%, and set the value between 20 and 50%. (pick a color halfway between the background and the sidebar, then make it dark and saturated)
  6. link: Interpolate between back, side, and text, then set the saturation to 100% and the value to 40%. (mix up the background, sidebar, and text colors to find something that stands out against all three, then force it to be fully saturated and slightly dark)
  7. visited: copy link and subtract 10% from the value. (a darker version of the link color)

So, how would you generate light text on a dark background? I hoped you’d never ask:

base: r=[0,100]; g=[0,100]; b=[0,100]
back: base; h+[-15,15]; v=[0,30]
side: base; h+[-90,90]; v=[15,25]
text: base; h+[-30,30]; v=[80,100]
head: back,side; v=[50,80]
link: back,side,text; v=60
visited: link; v+10

I’ve left out the saturation adjustments, and extended the brightness range for the background (0-10% would just look black most of the time).

Of course, you don’t have to generate all of the colors randomly. I usually force the text color to black, for instance: “text: #000000”.

Manually entering colors this way is a good way to tinker with an existing web site. After a physically painful visit to cut on the bias, I played with her color scheme and attempted to persuade her that #bb2222 on #6699ff would be easier on the eyes than #ff3333 on #6699ff. I still don’t like it, but at least it doesn’t give me a headache. No luck, though.