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 parameters
  • input: Any string to convert to a color

Returns

  • Ok(Color): A color from the gleam_community/colour package
  • Error(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 update
  • hash_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 = Red
  • 0.33 ≈ Green
  • 0.67 ≈ Blue
  • 1.0 = Red (wraps back)

Parameters

  • color_hash: The ColorHash to update
  • hue_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 cause to_color to 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.0 produces black
  • 0.5 produces pure color
  • 1.0 produces white

Parameters

  • color_hash: The ColorHash to update
  • lightnesses: 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 cause to_color to 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.0 produces grayscale (no color)
  • 1.0 produces fully saturated (pure) colors

Parameters

  • color_hash: The ColorHash to update
  • saturations: 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 cause to_color to 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])
Search Document