Creative Coding
Generative Color Palettes: Algorithms That Create Beautiful Harmonies
What if algorithms could generate color palettes as compelling as those crafted by experienced designers? They can—and increasingly, they do. From music visualizers to dynamic brand systems, generative color palettes combine mathematics, color science, and creative coding to produce harmonies that feel both structured and surprising.
Why Generate Palettes Algorithmically?
Manual palette creation works for one-off designs, but algorithmic generation enables:
- Scale: Generate thousands of unique palettes for dynamic content
- Consistency: Enforce rules (contrast, harmony, accessibility) programmatically
- Exploration: Discover combinations you'd never choose manually
- Responsiveness: Palettes that adapt to user preferences, time, or data
- Generative art: Each artwork gets unique, cohesive colors
Color Spaces Matter
Generating palettes in RGB often produces ugly results because RGB doesn't map to how humans perceive color. Better color spaces for generation:
HSL/HSB
Hue-Saturation-Lightness is intuitive for color harmony rules. Rotating hue creates complementary, triadic, and analogous relationships naturally.
- Pros: Intuitive, easy to implement harmony rules
- Cons: Perceptually non-uniform (same lightness value looks different across hues)
OKLCH
A perceptually uniform color space. Equal steps in OKLCH values produce visually equal color differences. The best modern choice for palette generation.
- Pros: Perceptually uniform, predictable results, CSS support (oklch())
- Cons: Some hue/chroma combinations produce out-of-gamut colors
CIELAB
Perceptually uniform, widely used in color science. Good for measuring color difference and generating evenly spaced palettes.
- Pros: Well-studied, good library support
- Cons: Not perfectly perceptually uniform (OKLCH is better)
Generation Algorithms
1. Color Wheel Harmonies
The simplest approach: pick a base hue and generate related hues using classic color theory relationships.
function complementary(baseHue) {
return [baseHue, (baseHue + 180) % 360];
}
function triadic(baseHue) {
return [baseHue, (baseHue + 120) % 360, (baseHue + 240) % 360];
}
function analogous(baseHue, spread = 30) {
return [baseHue - spread, baseHue, baseHue + spread];
}
function splitComplementary(baseHue) {
return [baseHue, (baseHue + 150) % 360, (baseHue + 210) % 360];
}Add saturation and lightness variations for complete palettes.
2. Golden Ratio Distribution
Use the golden ratio (0.618...) to distribute hues evenly around the color wheel:
function goldenRatioPalette(count, seed = Math.random()) {
const colors = [];
const goldenRatio = 0.618033988749895;
let hue = seed;
for (let i = 0; i < count; i++) {
hue = (hue + goldenRatio) % 1;
colors.push({
h: hue * 360,
s: 65 + Math.random() * 20, // 65-85%
l: 45 + Math.random() * 20, // 45-65%
});
}
return colors;
}The golden ratio ensures maximum hue separation regardless of how many colors you generate.
3. Constraint-Based Generation
Define rules and let the algorithm find palettes that satisfy all constraints:
- Minimum contrast ratio between text and background colors
- Maximum saturation range for visual cohesion
- Minimum perceptual distance between colors (no too-similar pairs)
- Accessibility requirements (WCAG compliance)
4. Image-Based Extraction
Extract dominant colors from photographs, artwork, or scenes:
- k-means clustering: Group pixel colors into k clusters; centroids become palette colors
- Median cut: Recursively split color space into regions; pick representative color from each
- Modified median cut: Weigh splits by color population for more representative palettes
// Simplified k-means color extraction
function extractPalette(pixels, k = 5) {
// 1. Initialize k random centroids
let centroids = randomSample(pixels, k);
// 2. Iterate until convergence
for (let i = 0; i < 20; i++) {
// Assign pixels to nearest centroid
const clusters = assignClusters(pixels, centroids);
// Update centroids to cluster means
centroids = clusters.map(c => mean(c));
}
return centroids; // The palette!
}5. Noise-Based Palettes
Use Perlin or Simplex noise to walk through color space, producing smooth, organic palette transitions:
function noisePalette(count, seed) {
return Array.from({ length: count }, (_, i) => ({
h: noise(i * 0.5, seed) * 360,
s: 50 + noise(i * 0.5, seed + 100) * 40,
l: 40 + noise(i * 0.5, seed + 200) * 30,
}));
}6. Machine Learning
Train models on curated palettes from designers (e.g., Coolors, Adobe Color datasets). GANs and transformers can learn what "looks good" from thousands of human-created palettes.
Applications
Generative Art
Each artwork gets a unique, cohesive palette. The palette becomes part of the art's identity—no two pieces look the same.
Dynamic Theming
Generate palettes from user avatars, album art, or uploaded images. Spotify does this for its Now Playing screen—the UI colors match the album art.
Data Visualization
Generate perceptually distinct palettes for any number of data categories. Ensure colors are distinguishable for colorblind users.
Brand Systems
Define a generative brand system: core colors with rules for generating extended palettes. Consistent yet flexible across campaigns and contexts.
Quality Evaluation
How do you know if a generated palette is "good"? Metrics to check:
- Contrast: Sufficient contrast between light and dark colors
- Distinguishability: Colors are perceptually distinct (check in CIELAB)
- Harmony: Colors feel cohesive, not random
- Accessibility: Meet WCAG contrast standards
- Coverage: Good range of lightness values for hierarchy
Generate Your Palettes
Explore algorithmic color generation with our Palette Generator. Choose from harmony-based, golden ratio, noise-based, and image extraction methods. Adjust parameters in real-time, check accessibility compliance, and export in CSS custom properties, JSON, or design tool formats.
Let algorithms inspire your next color scheme. The perfect palette might be one mathematical formula away.