abachrome

Why blend colors in OKLCH instead of RGB?

Blending colors directly in sRGB produces muddy midpoints — mixing a vivid blue and a vivid yellow through sRGB often yields a grey-green that looks dull and unpredictable. OKLCH (and its sibling OKLab) are perceptually uniform: equal numeric steps correspond to equal perceived differences, so midpoints look like what your eye actually expects.

The Difference in Practice

require 'abachrome'

blue   = Abachrome.from_hex('#0066ff')
yellow = Abachrome.from_hex('#ffcc00')

# Blend in sRGB (default for most libraries)
rgb_mid = blue.blend(yellow, 0.5)
puts Abachrome::Outputs::CSS.format(rgb_mid)   # => muddy green-grey

# Blend in OKLCH for a perceptually uniform midpoint
blue_lch   = blue.to_oklch
yellow_lch = yellow.to_oklch
lch_mid    = blue_lch.blend(yellow_lch, 0.5)
puts Abachrome::Outputs::CSS.format(lch_mid)   # => vibrant, balanced midpoint

Generating a Gradient Palette

require 'abachrome'

start_color = Abachrome.from_oklch(0.55, 0.22, 30)   # warm orange
end_color   = Abachrome.from_oklch(0.55, 0.22, 270)  # cool blue

palette = Abachrome::Palette.new([start_color, end_color])
steps   = palette.interpolate(steps: 7)

steps.each do |color|
  puts Abachrome::Outputs::CSS.format(color.to_srgb)
end

Because lightness and chroma are held constant while hue sweeps, every stop in the gradient has the same perceived brightness — making it suitable for accessible data-visualization color scales.

When RGB Blending Is Fine

Use sRGB blending when you need pixel-perfect reproduction of a design tool’s output, or when the two colors are close together and the perceptual difference is negligible.