# Generating a random hex color

Is there any better way of doing this?

function getRandomColor() {
var chars = '0123456789ABCDEF'.split('');
var hex = '#';
for (var i = 0; i < 6; i++) {
hex += chars[Math.floor(Math.random() * 16)];
}
return hex;
}


Hex colors can be in 3 digits or 6 digits. In the case where you want 3 digits, you can't do it because 6 is hardcoded. You may want to move it into a variable with a default value of 6.

Strings characters in JS are accessible via indices the same way as an array. So splitting the characters into an array is unnecessary, not to mention the additional memory consumed by creating an array.

Adding | 0 after a number truncates the decimal places from the number. Internally, it converts the internal representation of the number from a float into an integer, dropping the decimal information. So basically, it does the same thing as Math.floor, albeit in a more vague but shorter way.

You could also use reverse looping, and using the length as the condition. When length is zero, it's essentially falsy, thus stopping the loop.

function getRandomColor() {
var length = 6;
var chars = '0123456789ABCDEF';
var hex = '#';
while(length--) hex += chars[(Math.random() * 16) | 0];
return hex;
}

document.write(getRandomColor());

• Works like a charm thx! Commented Oct 20, 2015 at 13:28
• it's worth noting that any 3-digit hex color is also representable as a 6-digit hex-code, so unless you have a particular reason for wanting 3-digit colors, it's unimportant. (#ABC => #AABBCC.)
– j6m8
Commented Oct 20, 2015 at 22:54
• @j6m8 It's also worth noting that while it's unimportant, it's an option. Just because you can peel an apple doesn't mean you can't eat the skin. Commented Oct 20, 2015 at 22:57
• For sure! Although, to be really nitpicky, if you have a random distribution of 6-digit codes and 3-digit codes, you'll double the probability of those three-digit-representable colors ;D
– j6m8
Commented Oct 21, 2015 at 2:46

Edited: The first version was a little naive, and would sometimes return less than 6 digits. To ensure 6 digits, with leading zeroes, and allowing for pure white to be returned, we need to do some extra magic:

function getRandomColor() {
max = 1 << 24;
return '#' + (max + Math.floor(Math.random()*max)).toString(16).slice(-6);
}

// Lets generate some colors
document.write("<pre>");
for (i=0; i < 50; i++) {
document.write(getRandomColor()+ "  ");
if (i % 5 == 4) {
document.write("<br />");
}
}
document.write("</pre>");

First of all it adds the max, i.e. 0x1000000, to ensure leading zeroes, with the random number multiplied by max. This number is then converted into hexadecimal notation and we take the last six characters of this result. If you want only three digits, change the slice value. If extending for 24 bits, you'll also need to extend the max value approriately.

Edit hat tip to MarcDefiant: The code does now allow for pure white, 0xFFFFFF, and pads the returned number with leading zeroes.

You are discarding most of the random bits from the random numbers that you generated. All you need is a random integer between 0x000000 and 0xffffff, inclusive.

I would use a very similar solution to @holroy's. Also, I suggest dropping "get" from the function name, since it's generating rather than retrieving something.

function randomColor() {
var color = Math.floor(0x1000000 * Math.random()).toString(16);
return '#' + ('000000' + color).slice(-6);
}


Note that picking a color uniformly from the RGB color space might not be the best approach, depending on what you are using the color for. If you want to pick colors that are uniformly distributed according to human color perception, use the L-a-b color space instead, then convert the result to RGB.

• nice solution. what's the reason you aren't just returning '#' + color? Commented Oct 20, 2015 at 19:27
• @Jonah Zero padding. Commented Oct 20, 2015 at 19:30
• Wow, @200_success. I didn't know that. infinity * Thanks Commented Oct 21, 2015 at 12:34

This can be condensed and simplified a bit more.

Math.random().toString(16)


This line will return a decimal value which we want to turn into a String. We also want the number to be written in base 16. So, by doing these two methods we get a result that looks like this:

0.ae5782d36ac5331


All we need to do is skip past the zero and the decimal and grab the first 6 characters. We don't need to worry about padding because the length of the number that is returned by Math.random() will always be more than 6 digits.

This leaves us with the following:

return "#" + Math.random().toString(16).slice(2, 8);


The final step is adding the "#" in front of our 6 characters.