Skip to main content

Color Representation Components

When a color is defined with components, the numbers must be interpreted in the context of a declared colorRepresentation. This applies in two scenarios:

  1. Palette-level: When any color in a palette uses components, the palette must define a colorRepresentation that applies to all such colors.
  2. Color-level: Individual colors can specify alternative representations using altRepresentations, where each entry declares its own colorRepresentation.
Choosing between palette-level and color-level methods

Both approaches have distinct advantages and trade-offs depending on your use case.

Palette-level (colorRepresentation + components)

Pros:

  • Consistency - entire palette uses one color representation
  • Simpler tooling - tools know upfront what representation all colors are in
  • Smaller file size - no repeated colorRepresentation declarations

Cons:

  • Inflexible - can't mix color representations within one palette
  • Lossy conversion - if source colors are from different representations, you're forced to convert everything to one representation

Color-level (altRepresentations)

Pros:

  • Preserve original values - keep colors in their native representations without conversion
  • Multiple representations - same color in Lab, sRGB, OKLCH simultaneously
  • Tool flexibility - apps can pick the most appropriate representation

Cons:

  • Larger files - repeated colorRepresentation declarations and multiple representations
  • Complexity - tools must handle mixed color representations
  • Potential inconsistency - same color with different representations might not match exactly

Supported values by color representation

sRGB

  • Array form: [R, G, B] or [R, G, B, A]
  • Range: each component in [0, 1]
  • Alpha (optional): in [0, 1]

Example:

{
"components": [0.25, 0.5, 0.75, 1.0]
}

DisplayP3

  • Array form: [R, G, B] or [R, G, B, A]
  • Range: each component in [0, 1]
  • Alpha (optional): in [0, 1]

Example:

{
"components": [0.1, 0.6, 0.3]
}

Lab

Illuminant: D50 (per CSS Color Module 4)

  • Array form: [L, a, b] or [L, a, b, A]
  • Ranges:
    • L: 0 ≤ L ≤ 100
    • a/b: unbounded (schema does not clamp them)
    • Alpha (optional): 0 ≤ A ≤ 1
Lab Illuminant

PaletteJSON uses the D50 illuminant for Lab colors, following the CSS Color Module 4 standard. This matches the ICC v4 Profile Connection Space and ensures compatibility with web browsers and modern design tools.

If you're working with Lab colors using a D65 illuminant (common in scientific contexts), you must convert to D50 before including them in a PaletteJSON file.

Unbounded a/b Components

Values of a or b with very large magnitude may indicate an unrealistic color. The schema does not enforce limits here — linting tools can warn about suspicious values.

Example:

{
"components": [65.0, 30.5, -18.2]
}

Example with alpha:

{
"components": [65.0, 30.5, -18.2, 0.85]
}

OKLCH

  • Array form: [L, C, h] or [L, C, h, A]
  • Ranges:
    • L: 0 ≤ L ≤ 1
    • C: ≥ 0
    • h (hue): 0 ≤ h < 360
    • Alpha (optional): 0 ≤ A ≤ 1

Example:

{
"components": [0.72, 0.14, 210.5]
}

Example with alpha:

{
"components": [0.72, 0.14, 210.5, 0.5]
}

sRGB-linear-extended

  • Array form:

    • [R, G, B] (each a number, unbounded)
    • [R, G, B, A] where alpha ∈ [0, 1]
  • Notes:

    • Unlike gamma-encoded sRGB, these values are linear light.
    • No enforced min/max on R, G, B.

Example:

{
"components": [1.2, -0.1, 0.8, 0.5]
}

HSL

  • Array form: [H, S, L] or [H, S, L, A]
  • Ranges:
    • H (hue): 0 ≤ H < 360 (degrees)
    • S (saturation): 0 ≤ S ≤ 1
    • L (lightness): 0 ≤ L ≤ 1
    • Alpha (optional): 0 ≤ A ≤ 1

Example:

{
"components": [240, 0.8, 0.5, 1.0]
}

Validation rules

  • hex values are always treated as display sRGB, regardless of palette colorRepresentation.
  • components must match the palette's declared colorRepresentation.
  • altRepresentations entries are self-contained: each must declare its own colorRepresentation and follow the corresponding component validation rules.
  • If a palette mixes hex and components, the hex values remain in display sRGB; components follow the palette-level color representation.
See also