Chroma type number & Flavor<"Chroma">
import type {Chroma} from '@fuzdev/fuz_util/oklch.js'; OKLCH chroma, 0 or more and unbounded; sRGB colors stay below about 0.37.
external types
Flavored<number, 'Chroma'>OKLCH/OKLab ↔ sRGB conversions, gamut math, and oklch() strings.
The tuple-returning conversions allocate a fresh array per call, which is fine for most uses. Per-pixel or per-frame callers (a canvas gamut plane, a live chroma clamp) should use oklch_to_srgb_into, which writes into a caller-owned array. The gamut helpers allocate nothing.
Matrices and constants follow css-color-4 and Björn Ottosson's reference implementation.
18 declarations
Chroma type number & Flavor<"Chroma">
import type {Chroma} from '@fuzdev/fuz_util/oklch.js'; OKLCH chroma, 0 or more and unbounded; sRGB colors stay below about 0.37.
Flavored<number, 'Chroma'>([lightness, chroma, hue]: readonly [lightness: Lightness, chroma: Chroma, hue: Hue]): Oklch import {clamp_oklch} from '@fuzdev/fuz_util/oklch.js'; Clamps an OKLCH color the way the browser clamps a computed oklch():
lightness to [0, 1] and chroma to 0 or more. Derived values can overshoot
an end, and the browser renders the clamped color, so anything measuring
the rendered color has to clamp too.
__0Oklch (c: number): number import {linear_component_to_srgb} from '@fuzdev/fuz_util/oklch.js'; Converts a linear-light sRGB component to gamma-encoded in [0, 1].
cnumbernumber Oklab type [lightness: Lightness, a: number, b: number]
import type {Oklab} from '@fuzdev/fuz_util/oklch.js'; A color in OKLab: lightness in [0, 1], a/b roughly in [-0.4, 0.4].
([lightness, a, b]: readonly [lightness: Lightness, a: number, b: number]): Oklch import {oklab_to_oklch} from '@fuzdev/fuz_util/oklch.js'; Converts OKLab to OKLCH. Hue is normalized to [0, 360); an achromatic color (chroma below the float noise of the conversion matrices) gets hue 0.
__0readonly [lightness: Lightness, a: number, b: number]Oklch ([lightness, a, b]: readonly [lightness: Lightness, a: number, b: number]): RgbUnit import {oklab_to_srgb} from '@fuzdev/fuz_util/oklch.js'; Converts OKLab to gamma-encoded sRGB.
__0readonly [lightness: Lightness, a: number, b: number]RgbUnit components that may fall outside [0, 1] when the color is out of gamut
Oklch type [lightness: Lightness, chroma: Chroma, hue: Hue]
import type {Oklch} from '@fuzdev/fuz_util/oklch.js'; A color in OKLCH: lightness in [0, 1], chroma ≥ 0 (unbounded), hue in degrees.
(lch: readonly [lightness: Lightness, chroma: Chroma, hue: Hue], epsilon?: number): boolean import {oklch_in_srgb_gamut} from '@fuzdev/fuz_util/oklch.js'; Checks whether an OKLCH color converts to sRGB with all components inside [0, 1]. Allocates nothing, so it's safe in hot loops.
lchepsilontolerance for float noise at the gamut boundary
numberGAMUT_EPSILONboolean (lightness: Lightness, hue: Hue, precision?: number): Chroma import {oklch_max_srgb_chroma} from '@fuzdev/fuz_util/oklch.js'; Finds the largest chroma at a given OKLCH lightness and hue such that every chroma below it is also inside the sRGB gamut. Returns 0 when the lightness itself is out of range. Allocates nothing.
This is deliberately the *safe* maximum for ramps, not the outermost gamut
intersection: the sRGB gamut is non-convex in OKLab (most visibly near the
blue primary), so the constant-(L, H) chroma ray can exit and re-enter the
gamut. A ramp needs the whole [0, C] segment representable, so the scan
stops at the first exit.
lightnesshueprecisionterminate when the refinement interval is smaller than this
number1e-5([lightness, chroma, hue]: readonly [lightness: Lightness, chroma: Chroma, hue: Hue]): Oklab import {oklch_to_oklab} from '@fuzdev/fuz_util/oklch.js'; Converts OKLCH to OKLab.
__0Oklab (lch: readonly [lightness: Lightness, chroma: Chroma, hue: Hue]): RgbUnit import {oklch_to_srgb} from '@fuzdev/fuz_util/oklch.js'; Converts OKLCH to gamma-encoded sRGB.
lchRgbUnit components that may fall outside [0, 1] when the color is out of gamut
(lch: readonly [lightness: Lightness, chroma: Chroma, hue: Hue], out: RgbUnit): RgbUnit import {oklch_to_srgb_into} from '@fuzdev/fuz_util/oklch.js'; Converts OKLCH to gamma-encoded sRGB, writing into out instead of allocating.
For hot loops like per-pixel canvas fills; out may be reused across calls.
lchthe color to convert
outthe array to write the sRGB components into
RgbUnit out, with components that may fall outside [0, 1] when the color is out of gamut
out — overwrites all three components(lightness: Lightness, chroma: Chroma, hue: Hue): string import {oklch_to_string} from '@fuzdev/fuz_util/oklch.js'; Renders an OKLCH color as a CSS oklch() string, rounding lightness and
chroma to 4 decimals and hue to 2.
lightnesschromahuestring (value: string): Oklch import {parse_oklch_string} from '@fuzdev/fuz_util/oklch.js'; Parses a CSS oklch() string, with or without the oklch( wrapper.
Accepts percentages, a deg hue unit, none components (as 0), and
exponents. The alpha channel is accepted and ignored.
valuestringOklch Error - if the string isn't an `oklch()` colorRgbUnit type [r: number, g: number, b: number]
import type {RgbUnit} from '@fuzdev/fuz_util/oklch.js'; An RGB color with components in the unit interval [0, 1]. Values are gamma-encoded sRGB unless a function documents linear-light. Out-of-gamut results are not clamped, so components may fall outside [0, 1].
(c: number): number import {srgb_component_to_linear} from '@fuzdev/fuz_util/oklch.js'; Converts a gamma-encoded sRGB component in [0, 1] to linear-light.
cnumbernumber ([r, g, b]: readonly [r: number, g: number, b: number]): Oklab import {srgb_to_oklab} from '@fuzdev/fuz_util/oklch.js'; Converts gamma-encoded sRGB to OKLab.
__0readonly [r: number, g: number, b: number]Oklab (rgb: readonly [r: number, g: number, b: number]): Oklch import {srgb_to_oklch} from '@fuzdev/fuz_util/oklch.js'; Converts gamma-encoded sRGB to OKLCH.
rgbreadonly [r: number, g: number, b: number]Oklch