# Random color from string in javascript Consider a list of strings you need to permanently assign a random color. First you should turn the string into a hash. ```js var string = "string" var hash = 0 for (var i = 0; i < string.length; i++) { hash = string.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } console.log(hash) // -891985903 ``` * `string.charCodeAt(i)` returns the UTF-16 code for the character at index `i` * Bit operators work on 32 bits numbers. Any numeric operand in the operation is converted into a 32 bit number. * `hash << 5` is equivalent to `hash * Math.pow(2, 5)` (`hash * 32`), except the bit operator `<<` makes sure our result is a 32 bit number. * `hash & hash` again, makes sure we only return a 32 bit number. Now we have something to play around with. ### RGB The simplest method is to turn our hash into an RGB string: ```js String.prototype.toRGB = function() { var hash = 0; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { hash = this.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } var rgb = [0, 0, 0]; for (var i = 0; i < 3; i++) { var value = (hash >> (i * 8)) & 255; rgb[i] = value; } return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; } "string".toRGB() // rgb(17, 96, 213) ``` Or a hexadecimal string [(fiddle)](https://jsfiddle.net/8v6ys4x1/) ```js String.prototype.toHex = function() { var hash = 0; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { hash = this.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } var color = '#'; for (var i = 0; i < 3; i++) { var value = (hash >> (i * 8)) & 255; color += ('00' + value.toString(16)).substr(-2); } return color; } "string".toHex() // #1160d5 ``` The issue is this can potentially spit out *any* color value. Ideally we'd want to filter out values too similar to our background color, and some gray/bland colors. ### Color from array What if we hand pick some colors, and assign each string one of those? [(fiddle)](https://jsfiddle.net/wg6ymyyz/1/) ```js String.prototype.toColor = function() { var colors = ["#e51c23", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#5677fc", "#03a9f4", "#00bcd4", "#009688", "#259b24", "#8bc34a", "#afb42b", "#ff9800", "#ff5722", "#795548", "#607d8b"] var hash = 0; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { hash = this.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } hash = ((hash % colors.length) + colors.length) % colors.length; return colors[hash]; } "string".toColor() // #e91e63 ``` This method is better if we want to be very particular over what colors are allowed, but selecting a large number colors can get tedious. ### HSL How about we use the hash to pick a hue, then hardcode the intensity/lightness. [(fiddle)](https://jsfiddle.net/u3vc2efy/) ```js String.prototype.toHue = function() { var hash = 0; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { hash = this.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } return hash % 360; } "string".toHue() // -223 ``` **Note:** This can result in a negative value. CSS's `hsl()` handles values outside of `0..360` perfectly, but not everything does. For the sake of engineering, lets expand this out a bit more to include range values. [(fiddle)](https://jsfiddle.net/7zky3rbu/) ```js String.prototype.toHSL = function(opts) { var h, s, l; opts = opts || {}; opts.hue = opts.hue || [0, 360]; opts.sat = opts.sat || [75, 100]; opts.lit = opts.lit || [40, 60]; var range = function(hash, min, max) { var diff = max - min; var x = ((hash % diff) + diff) % diff; return x + min; } var hash = 0; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { hash = this.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } h = range(hash, opts.hue[0], opts.hue[1]); s = range(hash, opts.sat[0], opts.sat[1]); l = range(hash, opts.lit[0], opts.lit[1]); return `hsl(${h}, ${s}%, ${l}%)`; } "string".toHSL() // hsl(137, 97%, 57%) "string".toHSL({ hue: [-45, 45], sat: [75, 95], lit: [45, 55] }) // hsl(2, 92%, 52%) ```