colorhash
A library for generating deterministic colors from strings.
This library allows you to generate consistent, visually distinct colors from any string input. The same string will always produce the same color, making it perfect for generating colors for user avatars, data visualization, category coloring, or any use case where you need consistent colors without manually assigning them.
Basic Usage
import colorhash
import gleam_community/colour
let hasher = colorhash.new()
let assert Ok(color) = colorhash.to_color(hasher, "hello@example.com")
// Convert to hex for use in HTML/CSS
let hex = colour.to_rgb_hex_string(color)
// -> "53AC76"
Types
An opaque type that holds the configuration for generating colors.
The ColorHash type contains:
- A list of possible saturation values
- A list of possible lightness values
- A list of hue ranges to constrain generated colors
- A hash function to convert strings to integers
pub opaque type ColorHash
Values
pub fn new() -> ColorHash
Creates a new ColorHash with default configuration.
The default configuration provides a good balance of color variety and visual appeal for most use cases.
Default Values
- Saturations:
[0.35, 0.5, 0.65]- Moderately saturated colors - Lightnesses:
[0.35, 0.5, 0.65]- Medium brightness range - Hue ranges:
[#(0.0, 1.0)]- Full color spectrum - Hash function: SHA256 (cryptographically secure, good distribution)
Examples
let hasher = colorhash.new()
pub fn to_color(
color_hash: ColorHash,
input: String,
) -> Result(colour.Colour, Nil)
Generates a deterministic color from an input string.
This is the main function of the library. It takes a string input and produces a color based on the ColorHash configuration. The same input will always produce the same color.
Parameters
color_hash: The configured ColorHash containing generation parametersinput: Any string to convert to a color
Returns
Ok(Color): A color from thegleam_community/colourpackageError(Nil): If any configured values are outside the valid range[0.0, 1.0]
Behavior
- The hash value determines which saturation, lightness, and hue range are selected
- Empty configuration lists fall back to the default values
- Negative hash values are automatically converted to positive using absolute value
- Inverted hue ranges (where start > end) are treated as swapped ranges
- Unicode strings are fully supported
Error Cases
Returns Error(Nil) when:
- Any saturation value is outside
[0.0, 1.0] - Any lightness value is outside
[0.0, 1.0] - Any hue range start or end is outside
[0.0, 1.0]
Examples
let hasher = colorhash.new()
let assert Ok(color) = colorhash.to_color(hasher, "hello@example.com")
// Convert to hex for use in HTML/CSS
let hex = colour.to_rgb_hex_string(color)
// -> "53AC76"
pub fn with_hash_fun(
color_hash: ColorHash,
hash_fun: fn(String) -> Int,
) -> ColorHash
Sets a custom hash function for converting strings to integers.
The hash function determines how input strings are converted to numbers, which affects the color distribution and randomness.
Parameters
color_hash: The ColorHash to updatehash_fun: A function that takes a String and returns an Int
Behavior
- The default hash function uses SHA256 for cryptographically secure, well-distributed values
- Custom hash functions can be used for different distributions or performance characteristics
- Negative hash values are automatically converted to positive using absolute value
- The same input string should always produce the same hash value for deterministic colors
Examples
// Use a simple sum of character codes (less random but faster)
let simple_hasher =
colorhash.new()
|> colorhash.with_hash_fun(fn(s) {
s
|> string.to_utf_codepoints
|> list.map(string.utf_codepoint_to_int)
|> list.fold(0, int.add)
})
// Use a constant for testing
let test_hasher =
colorhash.new()
|> colorhash.with_hash_fun(fn(_) { 42 })
// Use string length (groups similar length strings)
let length_hasher =
colorhash.new()
|> colorhash.with_hash_fun(string.length)
pub fn with_hue_ranges(
color_hash: ColorHash,
hue_ranges: List(#(Float, Float)),
) -> ColorHash
Sets the list of hue ranges to constrain generated colors.
Hue determines the base color on the color wheel.
0.0= Red0.33≈ Green0.67≈ Blue1.0= Red (wraps back)
Parameters
color_hash: The ColorHash to updatehue_ranges: List of tuples#(start, end)where both values must be in[0.0, 1.0]
Behavior
- The hash value determines which hue range is selected from the list
- Within the selected range, the hash determines the exact hue value
- An empty list will cause the default range
[#(0.0, 1.0)]to be used - Values outside
[0.0, 1.0]will causeto_colorto return an error
Range Behavior
- Normal ranges: When
start < end, hues are generated between start and end - Inverted ranges: When
start > end, the range is treated as swapped (e.g.,#(0.8, 0.2)generates hues between 0.2 and 0.8) - Zero-width ranges: When
start == end, all generated hues will be exactly that value
Examples
// Warm colors only (reds, oranges, yellows)
let warm_hasher =
colorhash.new()
|> colorhash.with_hue_ranges([#(0.0, 0.17)])
// Cool colors only (blues, greens)
let cool_hasher =
colorhash.new()
|> colorhash.with_hue_ranges([#(0.33, 0.67)])
// Multiple distinct ranges
let multi_hasher =
colorhash.new()
|> colorhash.with_hue_ranges([
#(0.0, 0.1), // Reds
#(0.3, 0.4), // Greens
#(0.6, 0.7), // Blues
])
pub fn with_lightnesses(
color_hash: ColorHash,
lightnesses: List(Float),
) -> ColorHash
Sets the list of possible lightness values for generated colors.
Lightness controls the brightness of a color.
0.0produces black0.5produces pure color1.0produces white
Parameters
color_hash: The ColorHash to updatelightnesses: List of lightness values, each must be in range[0.0, 1.0]
Behavior
- The hash value determines which lightness is selected from the list
- An empty list will cause the default lightnesses
[0.35, 0.5, 0.65]to be used - Values outside
[0.0, 1.0]will causeto_colorto return an error
Examples
// Dark theme colors
let dark_hasher =
colorhash.new()
|> colorhash.with_lightnesses([0.2, 0.3, 0.4])
// Light theme colors
let light_hasher =
colorhash.new()
|> colorhash.with_lightnesses([0.7, 0.8, 0.9])
// High contrast (black or white tendency)
let contrast_hasher =
colorhash.new()
|> colorhash.with_lightnesses([0.1, 0.9])
pub fn with_saturations(
color_hash: ColorHash,
saturations: List(Float),
) -> ColorHash
Sets the list of possible saturation values for generated colors.
Saturation controls the intensity or purity of a color.
0.0produces grayscale (no color)1.0produces fully saturated (pure) colors
Parameters
color_hash: The ColorHash to updatesaturations: List of saturation values, each must be in range[0.0, 1.0]
Behavior
- The hash value determines which saturation is selected from the list
- An empty list will cause the default saturations
[0.35, 0.5, 0.65]to be used - Values outside
[0.0, 1.0]will causeto_colorto return an error
Examples
// Grayscale only
let gray_hasher =
colorhash.new()
|> colorhash.with_saturations([0.0])
// Vivid colors only
let vivid_hasher =
colorhash.new()
|> colorhash.with_saturations([0.8, 0.9, 1.0])
// Fixed saturation
let fixed_hasher =
colorhash.new()
|> colorhash.with_saturations([0.7])