PaletteJSON Specification
website·Indexed 29 days ago
https://palettejson.orgAn open JSON schema for defining color palettes in a structured, machine-readable way. The documentation covers the schema specification for root objects, palettes, colors, and accessibility, as well as guides on color space selection, gamut mapping, and precision.
What's inside PaletteJSON
- PaletteJSON is an open, machine-readable JSON schema used to define color palettes. It serves as an interoperable "hub" format (lingua franca) to allow color palettes to be easily stored, exchanged, and extended across various tools and workflows. Its design focuses on clarity (using standard JSON), extensibility (supporting metadata and multiple color spaces), and interoperability.
Overview of PaletteJSON schema
PaletteJSON is a JSON schema used to describe color palettes in a portable, machine-readable format. It is designed for developers, designers, and tool authors to consistently load, export, and share color systems, including associated metadata and accessibility information. The current stable version documented is v0.1, though the project is considered experimental and subject to future changes in features or validation rules.Parse and validate PaletteJSON files
Use a JSON schema validator (like Ajv) to ensure PaletteJSON files are compliant. When extracting colors, prefer thecomponentsarray over thehexstring for higher precision, using thecolorRepresentationfield to determine the color space.import Ajv from "ajv"; import addFormats from "ajv-formats"; import schema from "./palettejson.schema.json" assert { type: "json" }; import Color from "colorjs.io"; const ajv = new Ajv({ strict: false }); addFormats(ajv); const validate = ajv.compile(schema); const data = JSON.parse(fileContents); if (validate(data)) { const { colorRepresentation, colors } = data; const extracted = colors.map((color) => { if (color.components) { return new Color(colorRepresentation.toLowerCase(), color.components); } else if (color.hex) { return new Color(color.hex); } }); }Test color round-trip accuracy using colorjs.io
Verify if your decimal precision is sufficient by performing a round-trip conversion and calculating the perceptual difference (ΔE 2000). If the ΔE 2000 exceeds 1.0, increase the decimal precision by one place and test again.
Interpreting ΔE 2000 values:
- < 1.0: Imperceptible difference (Excellent).
- 1.0 - 2.0: Perceptible only under close comparison (Acceptable).
- 2.0 - 3.0: Noticeable difference (Marginally acceptable).
- > 3.0: Clearly visible difference (Insufficient precision).
import Color from "colorjs.io"; // Original sRGB color const original = new Color("srgb", [0.9608, 0.8784, 0.8627]); // Convert to Lab and back to sRGB const lab = original.to("lab"); const roundTrip = lab.to("srgb"); // Calculate perceptual difference const deltaE = original.deltaE(roundTrip, "2000"); console.log(`ΔE 2000: ${deltaE.toFixed(4)}`);Implement legibility guidance for UI consumers
When consuming PaletteJSON legibility data:
- Use
preferredTextas a high-level recommendation for direct UI application. - Treat
luminanceand contrast ratios as numeric hints, as different consumers may calculate them differently. - If the
legibilityobject or its properties are absent, the consumer should calculate or infer the legibility values as needed.
- Use
Maintain precision and test round-trip accuracy
Color conversions accumulate errors. To prevent perceptual drift, maintain 4-5 decimal places for Lab and OKLCH values. Verify critical brand colors by performing a 'round-trip' conversion (e.g., sRGB → Lab → sRGB) and ensuring the Delta E ($ΔE$) 2000 difference is less than 1.0.import Color from "colorjs.io"; function testRoundTrip(hexColor) { const original = new Color(hexColor); // Test via Lab const viaLab = original.to("lab").to("srgb"); const labDelta = original.deltaE(viaLab, "2000"); // Test via OKLCH const viaOKLCH = original.to("oklch").to("srgb"); const oklchDelta = original.deltaE(viaOKLCH, "2000"); return { labDelta, oklchDelta }; // Both should be < 1.0 } testRoundTrip("#f5e0dc");Recommended libraries for color conversion and validation
Use established libraries for color manipulation and schema validation to ensure precision and compliance.# Color Conversion npm install colorjs.io # JavaScript pip install coloraide # Python # Validation npm install ajv ajv-formats # Node.js pip install jsonschema # PythonBest practices for using PaletteJSON color references
When mapping PaletteJSON colors to external systems, follow these guidelines:
- Only provide references when you have an authoritative mapping.
- Use only one reference per system to maintain clarity.
- Use the
noteproperty to document any uncertainties or special cases regarding the mapping.
Perform color conversions using recommended libraries
Avoid implementing color space mathematics from scratch due to complexity and error risk. Use established libraries to handle gamma correction and edge cases.
Recommended Libraries:
- JavaScript:
colorjs.io,Culori - Python:
coloraide,color-science - Rust:
palette - Swift:
SwiftColor
// ✅ CORRECT: Use a library like colorjs.io import Color from "colorjs.io"; const hsl = new Color("srgb", [r, g, b]).to("hsl");- JavaScript:
Validate a PaletteJSON file using Node.js and AJV
PaletteJSON files can be validated against the officialpalettejson.schema.jsonusing JSON Schema draft 2020-12. In Node.js, this is typically done using theajvandajv-formatslibraries.// Install: npm i ajv ajv-formats import Ajv from "ajv"; import addFormats from "ajv-formats"; import schema from "./palettejson.schema.json" assert { type: "json" }; const data = { palettes: [ { name: "Example", slug: "example", type: "categorical", colors: [{ hex: "#FFFFFF" }, { hex: "#000000" }], }, ], }; const ajv = new Ajv({ strict: false }); addFormats(ajv); const validate = ajv.compile(schema); const valid = validate(data); if (valid) { console.log("Valid!"); } else { console.error("Validation errors:", validate.errors); }Manage HDR and Wide-Gamut workflows in PaletteJSON
PaletteJSON has specific constraints for high-dynamic-range and wide-gamut data:
- HDR (Rec. 2020, Dolby Vision): Use
sRGB-linear-extendedwith unbounded RGB values. Store HDR metadata externally as PaletteJSON does not natively support it. - ACES AP1: Not natively supported; store in
altRepresentations. - ICC Profiles: PaletteJSON does not embed ICC profiles. Store profile metadata in the
notesfield or reference external.iccfiles via the paletteslugorid.
- HDR (Rec. 2020, Dolby Vision): Use
Choose a PaletteJSON color representation
PaletteJSON supports six color representations optimized for different workflows. Use the following decision logic to select the appropriate one:
- Need wide-gamut colors beyond sRGB?
- Yes: Use DisplayP3 (modern displays) or sRGB-linear-extended (HDR workflows).
- No: Proceed to step 2.
- Need perceptually uniform color manipulation?
- Yes: Use OKLCH (modern) or Lab (industry standard).
- No: Proceed to step 3.
- Need intuitive hue-based controls for designers?
- Yes: Use HSL or OKLCH.
- No: Use sRGB (maximum compatibility).
- Need wide-gamut colors beyond sRGB?