Most solutions I've seen involve some kind of hard-coded hexadecimal conversion table, which is more than a little clunky. So here's another approach. Here, the value used to compute the colours is a ratio, with a value from 0.0 and up (normally in the 0.0 to 2.0 region, but theoretically unbounded at the top). I want to use red to indicate a ratio of 0.0, green for ratios of 2.0 or more, and a smooth range of colours in between.
var ratio = parseFloat(data["ratio"]);
var red = 255 - (ratio * 255); // calculate
var green = ratio * 128;
if (red < 0) red = 0; // clamp
if (green > 255) green = 255;
var colour = ((red << 16) | (green << 8) | 0).toString(16);
while (colour.length < 6) colour = '0' + colour;
document.getElementById("ratio").style.color = '#' + colour;
The magic is in knowing that colours are typically represented as a red-green-blue triplet, with a byte in each channel (range 0-255). Blue doesn't feature in our range, so it's always zero. So, assembling the necessary triplet is just a matter of getting the clamped value for the right fields, and then OR-ing them together in a bitwise fashion after putting the red and green values in the correct place with the appropriate shifting. Then the
toString(16)returns that integer in base-16, which happens to be what makes sense in CSS land. Finally, pad the string out with zeroes on the left (the string needs to be six characters long, then slap on the '#' to have it make sense in CSS land and you're done.