ruby 41 lines · 7 steps

Deriving a stable color from a username

Hash a username into a hue, then convert HSL to a hex color so each user gets a consistent, well-spread avatar color.

Explained by highlit
1class UserColor
2 GOLDEN_RATIO_CONJUGATE = 0.618033988749895
3 
4 def initialize(username)
5 @username = username.to_s
6 end
7 
8 def to_hex
9 r, g, b = rgb
10 format("#%02x%02x%02x", r, g, b)
11 end
12 
13 def rgb
14 hsl_to_rgb(hue, 0.5, 0.6)
15 end
16 
17 private
18 
19 def hue
20 digest = Digest::SHA256.hexdigest(@username).to_i(16)
21 ((digest % 360) / 360.0 + GOLDEN_RATIO_CONJUGATE) % 1.0
22 end
23 
24 def hsl_to_rgb(h, s, l)
25 c = (1 - (2 * l - 1).abs) * s
26 x = c * (1 - ((h * 6) % 2 - 1).abs)
27 m = l - c / 2
28 
29 r, g, b =
30 case (h * 6).floor
31 when 0 then [c, x, 0]
32 when 1 then [x, c, 0]
33 when 2 then [0, c, x]
34 when 3 then [0, x, c]
35 when 4 then [x, 0, c]
36 else [c, 0, x]
37 end
38 
39 [r, g, b].map { |v| ((v + m) * 255).round.clamp(0, 255) }
40 end
41end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Hashing an identifier gives you a deterministic value you can map into any range you need.
  2. 2Nudging a hue by the golden ratio conjugate spreads sequential values across the color wheel for better visual distinction.
  3. 3Splitting color math into HSL selection and RGB conversion keeps the pleasing-color logic separate from the pixel format.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Deriving a stable color from a username — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code