πŸ‘‘ A tiny yet powerful tool for high-performance color manipulations and conversions

Overview
Colord is a tiny yet powerful tool for high-performance color manipulations and conversions.

Features

  • πŸ“¦ Small: Just 1.7 KB gzipped (3x+ lighter than color and tinycolor2)
  • πŸš€ Fast: 3x+ faster than color and tinycolor2
  • 😍 Simple: Chainable API and familiar patterns
  • πŸ’ͺ Immutable: No need to worry about data mutations
  • πŸ›‘ Bulletproof: Written in strict TypeScript and has 100% test coverage
  • πŸ—‚ Typed: Ships with types included
  • πŸ— Extendable: Built-in plugin system to add new functionality
  • πŸ“š CSS-compliant: Strictly follows CSS Color Level specifications
  • πŸ‘« Works everywhere: Supports all browsers and Node.js
  • πŸ’¨ Dependency-free
---

Benchmarks

Library Operations/sec Size
(minified)
Size
(gzipped)
Dependencies Type declarations
colord πŸ‘‘ 3,524,989
color 744,263
tinycolor2 971,312
ac-colors 660,722
chroma-js 962,967

The performance results were generated on a MBP 2019, 2,6 GHz Intel Core i7 by running npm run benchmark in the library folder. See tests/benchmark.ts.

---

Getting Started

npm i colord
import { colord } from "colord";

colord("#ff0000").grayscale().alpha(0.25).toRgbString(); // "rgba(128, 128, 128, 0.25)"
colord("rgb(192, 192, 192)").isLight(); // true
colord("hsl(0, 50%, 50%)").darken(0.25).toHex(); // "#602020"
---

Supported Color Models

  • Hexadecimal strings (including 3, 4 and 8 digit notations)
  • RGB strings and objects
  • HSL strings and objects
  • HSV objects
  • Color names (via plugin)
  • HWB objects and strings (via plugin)
  • CMYK objects and strings (via plugin)
  • LCH objects and strings (via plugin)
  • LAB objects (via plugin)
  • XYZ objects (via plugin)
---

API

Color parsing

colord(input)

Parses the given input and creates a new Colord instance. String parsing strictly conforms to CSS Color Level Specifications.

import { colord } from "colord";

// String input examples
colord("#FFF");
colord("#ffffff");
colord("#ffffffff");
colord("rgb(255, 255, 255)");
colord("rgba(255, 255, 255, 0.5)");
colord("rgba(100% 100% 100% / 50%)");
colord("hsl(90, 100%, 100%)");
colord("hsla(90, 100%, 100%, 0.5)");
colord("hsla(90deg 100% 100% / 50%)");
colord("tomato"); // requires "names" plugin

// Object input examples
colord({ r: 255, g: 255, b: 255 });
colord({ r: 255, g: 255, b: 255, a: 1 });
colord({ h: 360, s: 100, l: 100 });
colord({ h: 360, s: 100, l: 100, a: 1 });
colord({ h: 360, s: 100, v: 100 });
colord({ h: 360, s: 100, v: 100, a: 1 });

Check out the "Plugins" section for more input format examples.

getFormat(input)

Returns a color model name for the input passed to the function. Uses the same parsing system as colord function.

import { getFormat } from "colord";

getFormat("#aabbcc"); // "hex"
getFormat({ r: 13, g: 237, b: 162, a: 0.5 }); // "rgb"
getFormat("hsl(180deg, 50%, 50%)"); // "hsl"
getFormat("WUT?"); // undefined

Color conversion

.toHex()

Returns the hexadecimal representation of a color. When the alpha channel value of the color is less than 1, it outputs #rrggbbaa format instead of #rrggbb.

colord("rgb(0, 255, 0)").toHex(); // "#00ff00"
colord({ h: 300, s: 100, l: 50 }).toHex(); // "#ff00ff"
colord({ r: 255, g: 255, b: 255, a: 0 }).toHex(); // "#ffffff00"
.toRgb()
colord("#ff0000").toRgb(); // { r: 255, g: 0, b: 0, a: 1 }
colord({ h: 180, s: 100, l: 50, a: 0.5 }).toRgb(); // { r: 0, g: 255, b: 255, a: 0.5 }
.toRgbString()
colord("#ff0000").toRgbString(); // "rgb(255, 0, 0)"
colord({ h: 180, s: 100, l: 50, a: 0.5 }).toRgbString(); // "rgba(0, 255, 255, 0.5)"
.toHsl()

Converts a color to HSL color space and returns an object.

colord("#ffff00").toHsl(); // { h: 60, s: 100, l: 50, a: 1 }
colord("rgba(0, 0, 255, 0.5) ").toHsl(); // { h: 240, s: 100, l: 50, a: 0.5 }
.toHslString()

Converts a color to HSL color space and expresses it through the functional notation.

colord("#ffff00").toHslString(); // "hsl(60, 100%, 50%)"
colord("rgba(0, 0, 255, 0.5)").toHslString(); // "hsla(240, 100%, 50%, 0.5)"
.toHsv()

Converts a color to HSV color space and returns an object.

colord("#ffff00").toHsv(); // { h: 60, s: 100, v: 100, a: 1 }
colord("rgba(0, 255, 255, 0.5) ").toHsv(); // { h: 180, s: 100, v: 100, a: 1 }
.toName(options?) (names plugin)

Converts a color to a CSS keyword. Returns undefined if the color is not specified in the specs.

import { colord, extend } from "colord";
import namesPlugin from "colord/plugins/names";

extend([namesPlugin]);

colord("#ff6347").toName(); // "tomato"
colord("#00ffff").toName(); // "cyan"
colord("rgba(0, 0, 0, 0)").toName(); // "transparent"

colord("#fe0000").toName(); // undefined (the color is not specified in CSS specs)
colord("#fe0000").toName({ closest: true }); // "red" (closest color available)
.toCmyk() (cmyk plugin)

Converts a color to CMYK color space.

import { colord, extend } from "colord";
import cmykPlugin from "colord/plugins/cmyk";

extend([cmykPlugin]);

colord("#ffffff").toCmyk(); // { c: 0, m: 0, y: 0, k: 0, a: 1 }
colord("#555aaa").toCmyk(); // { c: 50, m: 47, y: 0, k: 33, a: 1 }
.toCmykString() (cmyk plugin)

Converts a color to color space.

Converts a color to CMYK color space and expresses it through the functional notation

import { colord, extend } from "colord";
import cmykPlugin from "colord/plugins/cmyk";

extend([cmykPlugin]);

colord("#99ffff").toCmykString(); // "device-cmyk(40% 0% 0% 0%)"
colord("#00336680").toCmykString(); // "device-cmyk(100% 50% 0% 60% / 0.5)"
.toHwb() (hwb plugin)

Converts a color to HWB (Hue-Whiteness-Blackness) color space.

import { colord, extend } from "colord";
import hwbPlugin from "colord/plugins/hwb";

extend([hwbPlugin]);

colord("#ffffff").toHwb(); // { h: 0, w: 100, b: 0, a: 1 }
colord("#555aaa").toHwb(); // { h: 236, w: 33, b: 33, a: 1 }
.toHwbString() (hwb plugin)

Converts a color to HWB (Hue-Whiteness-Blackness) color space and expresses it through the functional notation.

import { colord, extend } from "colord";
import hwbPlugin from "colord/plugins/hwb";

extend([hwbPlugin]);

colord("#999966").toHwbString(); // "hwb(60 40% 40%)"
colord("#99ffff").toHwbString(); // "hwb(180 60% 0%)"
colord("#003366").alpha(0.5).toHwbString(); // "hwb(210 0% 60% / 0.5)"
.toLab() (lab plugin)

Converts a color to CIE LAB color space. The conversion logic is ported from CSS Color Module Level 4 Specification.

import { colord, extend } from "colord";
import labPlugin from "colord/plugins/lab";

extend([labPlugin]);

colord("#ffffff").toLab(); // { l: 100, a: 0, b: 0, alpha: 1 }
colord("#33221180").toLab(); // { l: 14.89, a: 5.77, b: 14.41, alpha: 0.5 }
.toLch() (lch plugin)

Converts a color to CIE LCH color space. The conversion logic is ported from CSS Color Module Level 4 Specification.

import { colord, extend } from "colord";
import lchPlugin from "colord/plugins/lch";

extend([lchPlugin]);

colord("#ffffff").toLch(); // { l: 100, c: 0, h: 0, a: 1 }
colord("#213b0b").toLch(); // { l: 21.85, c: 31.95, h: 127.77, a: 1 }
.toLchString() (lch plugin)

Converts a color to CIE LCH color space and expresses it through the functional notation.

import { colord, extend } from "colord";
import lchPlugin from "colord/plugins/lch";

extend([lchPlugin]);

colord("#ffffff").toLchString(); // "lch(100% 0 0)"
colord("#213b0b").alpha(0.5).toLchString(); // "lch(21.85% 31.95 127.77 / 0.5)"
.toXyz() (xyz plugin)

Converts a color to CIE XYZ color space. The conversion logic is ported from CSS Color Module Level 4 Specification.

import { colord, extend } from "colord";
import xyzPlugin from "colord/plugins/xyz";

extend([xyzPlugin]);

colord("#ffffff").toXyz(); // { x: 95.047, y: 100, z: 108.883, a: 1 }

Color manipulation

.alpha(value)

Changes the alpha channel value and returns a new Colord instance.

colord("rgb(0, 0, 0)").alpha(0.5).toRgbString(); // "rgba(0, 0, 0, 0.5)"
.invert()

Creates a new Colord instance containing an inverted (opposite) version of the color.

colord("#ffffff").invert().toHex(); // "#000000"
colord("#aabbcc").invert().toHex(); // "#554433"
.saturate(amount = 0.1)

Increases the HSL saturation of a color by the given amount.

colord("#bf4040").saturate(0.25).toHex(); // "#df2020"
colord("hsl(0, 50%, 50%)").saturate(0.5).toHslString(); // "hsl(0, 100%, 50%)"
.desaturate(amount = 0.1)

Decreases the HSL saturation of a color by the given amount.

colord("#df2020").saturate(0.25).toHex(); // "#bf4040"
colord("hsl(0, 100%, 50%)").saturate(0.5).toHslString(); // "hsl(0, 50%, 50%)"
.grayscale()

Makes a gray color with the same lightness as a source color. Same as calling desaturate(1).

colord("#bf4040").grayscale().toHex(); // "#808080"
colord("hsl(0, 100%, 50%)").grayscale().toHslString(); // "hsl(0, 0%, 50%)"
.lighten(amount = 0.1)

Increases the HSL lightness of a color by the given amount.

colord("#000000").lighten(0.5).toHex(); // "#808080"
colord("#223344").lighten(0.3).toHex(); // "#5580aa"
colord("hsl(0, 50%, 50%)").lighten(0.5).toHslString(); // "hsl(0, 50%, 100%)"
.darken(amount = 0.1)

Decreases the HSL lightness of a color by the given amount.

colord("#ffffff").darken(0.5).toHex(); // "#808080"
colord("#5580aa").darken(0.3).toHex(); // "#223344"
colord("hsl(0, 50%, 100%)").lighten(0.5).toHslString(); // "hsl(0, 50%, 50%)"
.hue(value)

Changes the hue value and returns a new Colord instance.

colord("hsl(90, 50%, 50%)").hue(180).toHslString(); // "hsl(180, 50%, 50%)"
colord("hsl(90, 50%, 50%)").hue(370).toHslString(); // "hsl(10, 50%, 50%)"
.rotate(amount = 15)

Increases the HSL hue value of a color by the given amount.

colord("hsl(90, 50%, 50%)").rotate(90).toHslString(); // "hsl(180, 50%, 50%)"
colord("hsl(90, 50%, 50%)").rotate(-180).toHslString(); // "hsl(270, 50%, 50%)"
.mix(color2, ratio = 0.5) (mix plugin)

Produces a mixture of two colors and returns the result of mixing them (new Colord instance).

In contrast to other libraries that perform RGB values mixing, Colord mixes colors through LAB color space. This approach produces better results and doesn't have the drawbacks the legacy way has.

β†’ Online demo

import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/mix";

extend([mixPlugin]);

colord("#ffffff").mix("#000000").toHex(); // "#777777"
colord("#800080").mix("#dda0dd").toHex(); // "#af5cae"
colord("#cd853f").mix("#eee8aa", 0.6).toHex(); // "#e3c07e"
colord("#008080").mix("#808000", 0.35).toHex(); // "#50805d"
.tints(count = 5) (mix plugin)

Provides functionality to generate tints of a color. Returns an array of Colord instances, including the original color.

import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/mix";

extend([mixPlugin]);

const color = colord("#ff0000");
color.tints(3).map((c) => c.toHex()); // ["#ff0000", "#ff9f80", "#ffffff"];
.shades(count = 5) (mix plugin)

Provides functionality to generate shades of a color. Returns an array of Colord instances, including the original color.

import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/mix";

extend([mixPlugin]);

const color = colord("#ff0000");
color.shades(3).map((c) => c.toHex()); // ["#ff0000", "#7a1b0b", "#000000"];
.tones(count = 5) (mix plugin)

Provides functionality to generate tones of a color. Returns an array of Colord instances, including the original color.

import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/mix";

extend([mixPlugin]);

const color = colord("#ff0000");
color.tones(3).map((c) => c.toHex()); // ["#ff0000", "#c86147", "#808080"];
.harmonies(type = "complementary") (harmonies plugin)

Provides functionality to generate harmony colors. Returns an array of Colord instances.

import { colord, extend } from "colord";
import harmoniesPlugin from "colord/plugins/harmonies";

extend([harmoniesPlugin]);

const color = colord("#ff0000");
color.harmonies("analogous").map((c) => c.toHex()); // ["#ff0080", "#ff0000", "#ff8000"]
color.harmonies("complementary").map((c) => c.toHex()); // ["#ff0000", "#00ffff"]
color.harmonies("double-split-complementary").map((c) => c.toHex()); // ["#ff0080", "#ff0000", "#ff8000", "#00ff80", "#0080ff"]
color.harmonies("rectangle").map((c) => c.toHex()); // ["#ff0000", "#ffff00", "#00ffff", "#0000ff"]
color.harmonies("split-complementary").map((c) => c.toHex()); // ["#ff0000", "#00ff80", "#0080ff"]
color.harmonies("tetradic").map((c) => c.toHex()); // ["#ff0000", "#80ff00", "#00ffff", "#8000ff"]
color.harmonies("triadic").map((c) => c.toHex()); // ["#ff0000", "#00ff00", "#0000ff"]

Color analysis

.isValid()

Returns a boolean indicating whether or not an input has been parsed successfully. Note: If parsing is unsuccessful, Colord defaults to black (does not throws an error).

colord("#ffffff").isValid(); // true
colord("#wwuutt").isValid(); // false
colord("abracadabra").isValid(); // false
colord({ r: 0, g: 0, b: 0 }).isValid(); // true
colord({ r: 0, g: 0, v: 0 }).isValid(); // false
.isEqual(color2)

Determines whether two values are the same color.

colord("#000000").isEqual("rgb(0, 0, 0)"); // true
colord("#000000").isEqual("rgb(255, 255, 255)"); // false
.alpha()
colord("#ffffff").alpha(); // 1
colord("rgba(50, 100, 150, 0.5)").alpha(); // 0.5
.hue()
colord("hsl(90, 50%, 50%)").hue(); // 90
colord("hsl(-10, 50%, 50%)").hue(); // 350
.brightness()

Returns the brightness of a color (from 0 to 1). The calculation logic is modified from Web Content Accessibility Guidelines.

colord("#000000").brightness(); // 0
colord("#808080").brightness(); // 0.5
colord("#ffffff").brightness(); // 1
.isLight()

Same as calling brightness() >= 0.5.

colord("#111111").isLight(); // false
colord("#aabbcc").isLight(); // true
colord("#ffffff").isLight(); // true
.isDark()

Same as calling brightness() < 0.5.

colord("#111111").isDark(); // true
colord("#aabbcc").isDark(); // false
colord("#ffffff").isDark(); // false
.luminance() (a11y plugin)

Returns the relative luminance of a color, normalized to 0 for darkest black and 1 for lightest white as defined by WCAG 2.0.

colord("#000000").luminance(); // 0
colord("#808080").luminance(); // 0.22
colord("#ccddee").luminance(); // 0.71
colord("#ffffff").luminance(); // 1
.contrast(color2 = "#FFF") (a11y plugin)

Calculates a contrast ratio for a color pair. This luminance difference is expressed as a ratio ranging from 1 (e.g. white on white) to 21 (e.g., black on a white). WCAG Accessibility Level AA requires a ratio of at least 4.5 for normal text and 3 for large text.

colord("#000000").contrast(); // 21 (black on white)
colord("#ffffff").contrast("#000000"); // 21 (white on black)
colord("#777777").contrast(); // 4.47 (gray on white)
colord("#ff0000").contrast(); // 3.99 (red on white)
colord("#0000ff").contrast("#ff000"); // 2.14 (blue on red)
.isReadable(color2 = "#FFF", options?) (a11y plugin)

Checks that a background and text color pair is readable according to WCAG 2.0 Contrast and Color Requirements.

colord("#000000").isReadable(); // true (normal black text on white bg conforms to WCAG AA)
colord("#777777").isReadable(); // false (normal gray text on white bg conforms to WCAG AA)
colord("#ffffff").isReadable("#000000"); // true (normal white text on black bg conforms to WCAG AA)
colord("#e60000").isReadable("#ffff47"); // true (normal red text on yellow bg conforms to WCAG AA)
colord("#e60000").isReadable("#ffff47", { level: "AAA" }); // false (normal red text on yellow bg does not conform to WCAG AAA)
colord("#e60000").isReadable("#ffff47", { level: "AAA", size: "large" }); // true (large red text on yellow bg conforms to WCAG AAA)
.delta(color2 = "#FFF") (lab plugin)

Calculates the perceived color difference between two colors. The difference calculated according to Delta E2000. The return value is 0 if the colors are equal, 1 if they are entirely different.

colord("#3296fa").delta("#197dc8"); // 0.099
colord("#faf0c8").delta("#ffffff"); // 0.148
colord("#afafaf").delta("#b4b4b4"); // 0.014
colord("#000000").delta("#ffffff"); // 1

Color utilities

random()

Returns a new Colord instance with a random color value inside.

import { random } from "colord";

random().toHex(); // "#01c8ec"
random().alpha(0.5).toRgb(); // { r: 13, g: 237, b: 162, a: 0.5 }
.minify(options?)

Converts a color to its shortest string representation.

import { colord, extend } from "colord";
import minifyPlugin from "colord/plugins/minify";

extend([minifyPlugin]);

colord("black").minify(); // "#000"
colord("#112233").minify(); // "#123"
colord("darkgray").minify(); // "#a9a9a9"
colord("rgba(170,170,170,0.4)").minify(); // "hsla(0,0%,67%,.4)"
colord("rgba(170,170,170,0.4)").minify({ alphaHex: true }); // "#aaa6"
Option Default Description
hex true Enable #rrggbb and #rgb notations
alphaHex false Enable #rrggbbaa and #rgba notations
rgb true Enable rgb() and rgba() functional notations
hsl true Enable hsl() and hsla() functional notations
name false Enable CSS color keywords. Requires names plugin installed
transparent false Enable "transparent" color keyword
---

Plugins

Colord has a built-in plugin system that allows new features and functionality to be easily added.

a11y (Accessibility) 0.38 KB

Adds accessibility and color contrast utilities working according to Web Content Accessibility Guidelines 2.0.

import { colord, extend } from "colord";
import a11yPlugin from "colord/plugins/a11y";

extend([a11yPlugin]);

colord("#000000").luminance(); // 0
colord("#ccddee").luminance(); // 0.71
colord("#ffffff").luminance(); // 1

colord("#000000").contrast(); // 21 (black on white)
colord("#ffffff").contrast("#000000"); // 21 (white on black)
colord("#0000ff").contrast("#ff000"); // 2.14 (blue on red)

colord("#000000").isReadable(); // true (black on white)
colord("#ffffff").isReadable("#000000"); // true (white on black)
colord("#777777").isReadable(); // false (gray on white)
colord("#e60000").isReadable("#ffff47"); // true (normal red text on yellow bg conforms to WCAG AA)
colord("#e60000").isReadable("#ffff47", { level: "AAA" }); // false (normal red text on yellow bg does not conform to WCAG AAA)
colord("#e60000").isReadable("#ffff47", { level: "AAA", size: "large" }); // true (large red text on yellow bg conforms to WCAG AAA)
cmyk (CMYK color space) 0.6 KB

Adds support of CMYK color model.

import { colord, extend } from "colord";
import cmykPlugin from "colord/plugins/cmyk";

extend([cmykPlugin]);

colord("#ffffff").toCmyk(); // { c: 0, m: 0, y: 0, k: 0, a: 1 }
colord("#999966").toCmykString(); // "device-cmyk(0% 0% 33% 40%)"
colord({ c: 0, m: 0, y: 0, k: 100, a: 1 }).toHex(); // "#000000"
colord("device-cmyk(0% 61% 72% 0% / 50%)").toHex(); // "#ff634780"
harmonies (Color harmonies) 0.15 KB

Provides functionality to generate harmony colors.

import { colord, extend } from "colord";
import harmonies from "colord/plugins/harmonies";

extend([harmonies]);

const color = colord("#ff0000");
color.harmonies("analogous").map((c) => c.toHex()); // ["#ff0080", "#ff0000", "#ff8000"]
color.harmonies("complementary").map((c) => c.toHex()); // ["#ff0000", "#00ffff"]
color.harmonies("double-split-complementary").map((c) => c.toHex()); // ["#ff0080", "#ff0000", "#ff8000", "#00ff80", "#0080ff"]
color.harmonies("rectangle").map((c) => c.toHex()); // ["#ff0000", "#ffff00", "#00ffff", "#0000ff"]
color.harmonies("split-complementary").map((c) => c.toHex()); // ["#ff0000", "#00ff80", "#0080ff"]
color.harmonies("tetradic").map((c) => c.toHex()); // ["#ff0000", "#80ff00", "#00ffff", "#8000ff"]
color.harmonies("triadic").map((c) => c.toHex()); // ["#ff0000", "#00ff00", "#0000ff"]
hwb (HWB color model) 0.8 KB

Adds support of Hue-Whiteness-Blackness color model.

import { colord, extend } from "colord";
import hwbPlugin from "colord/plugins/hwb";

extend([hwbPlugin]);

colord("#999966").toHwb(); // { h: 60, w: 40, b: 40, a: 1 }
colord("#003366").toHwbString(); // "hwb(210 0% 60%)"

colord({ h: 60, w: 40, b: 40 }).toHex(); // "#999966"
colord("hwb(210 0% 60% / 50%)").toHex(); // "#00336680"
lab (CIE LAB color space) 1.4 KB

Adds support of CIE LAB color model. The conversion logic is ported from CSS Color Module Level 4 Specification.

Also plugin provides .delta method for perceived color difference calculations.

import { colord, extend } from "colord";
import labPlugin from "colord/plugins/lab";

extend([labPlugin]);

colord({ l: 53.24, a: 80.09, b: 67.2 }).toHex(); // "#ff0000"
colord("#ffffff").toLab(); // { l: 100, a: 0, b: 0, alpha: 1 }

colord("#afafaf").delta("#b4b4b4"); // 0.014
colord("#000000").delta("#ffffff"); // 1
lch (CIE LCH color space) 1.3 KB

Adds support of CIE LCH color space. The conversion logic is ported from CSS Color Module Level 4 Specification.

import { colord, extend } from "colord";
import lchPlugin from "colord/plugins/lch";

extend([lchPlugin]);

colord({ l: 100, c: 0, h: 0 }).toHex(); // "#ffffff"
colord("lch(48.25% 30.07 196.38)").toHex(); // "#008080"

colord("#646464").toLch(); // { l: 42.37, c: 0, h: 0, a: 1 }
colord("#646464").alpha(0.5).toLchString(); // "lch(42.37% 0 0 / 0.5)"
minify (Color string minification) 0.5 KB

A plugin adding color string minification utilities.

import { colord, extend } from "colord";
import minifyPlugin from "colord/plugins/minify";

extend([minifyPlugin]);

colord("black").minify(); // "#000"
colord("#112233").minify(); // "#123"
colord("darkgray").minify(); // "#a9a9a9"
colord("rgba(170,170,170,0.4)").minify(); // "hsla(0,0%,67%,.4)"
colord("rgba(170,170,170,0.4)").minify({ alphaHex: true }); // "#aaa6"
mix (Color mixing) 0.96 KB

A plugin adding color mixing utilities.

In contrast to other libraries that perform RGB values mixing, Colord mixes colors through LAB color space. This approach produces better results and doesn't have the drawbacks the legacy way has.

β†’ Online demo

import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/mix";

extend([mixPlugin]);

colord("#ffffff").mix("#000000").toHex(); // "#777777"
colord("#800080").mix("#dda0dd").toHex(); // "#af5cae"
colord("#cd853f").mix("#eee8aa", 0.6).toHex(); // "#e3c07e"
colord("#008080").mix("#808000", 0.35).toHex(); // "#50805d"

Also, the plugin provides special mixtures such as tints, shades, and tones:

tints, shades, and tones mixtures
const color = colord("#ff0000");
color.tints(3).map((c) => c.toHex()); // ["#ff0000", "#ff9f80", "#ffffff"];
color.shades(3).map((c) => c.toHex()); // ["#ff0000", "#7a1b0b", "#000000"];
color.tones(3).map((c) => c.toHex()); // ["#ff0000", "#c86147", "#808080"];
names (CSS color keywords) 1.45 KB

Provides options to convert a color into a CSS color keyword and vice versa.

import { colord, extend } from "colord";
import namesPlugin from "colord/plugins/names";

extend([namesPlugin]);

colord("tomato").toHex(); // "#ff6347"
colord("#00ffff").toName(); // "cyan"
colord("rgba(0, 0, 0, 0)").toName(); // "transparent"
colord("#fe0000").toName(); // undefined (the color is not specified in CSS specs)
colord("#fe0000").toName({ closest: true }); // "red" (closest color)
xyz (CIE XYZ color space) 0.7 KB

Adds support of CIE XYZ color model. The conversion logic is ported from CSS Color Module Level 4 Specification.

import { colord, extend } from "colord";
import xyzPlugin from "colord/plugins/xyz";

extend([xyzPlugin]);

colord("#ffffff").toXyz(); // { x: 95.047, y: 100, z: 108.883, a: 1 }
colord({ x: 0, y: 0, z: 0 }).toHex(); // "#000000"
---

Types

Colord is written in strict TypeScript and ships with types in the library itself β€” no need for any other install. We provide everything you need in one tiny package.

While not only typing its own functions and variables, Colord can also help you type yours. Depending on the color space you are using, you can also import and use the type that is associated with it.

import { RgbColor, RgbaColor, HslColor, HslaColor, HsvColor, HsvaColor } from "colord";

const foo: HslColor = { h: 0, s: 0, l: 0 };
const bar: RgbColor = { r: 0, g: 0, v: 0 }; // ERROR
---

Projects using Colord

  • cssnano β€” the most popular CSS minification tool
  • Resume.io β€” online resume builder with over 12,000,000 users worldwide
  • Leva β€” open source extensible GUI panel made for React
  • Qui Max β€” Vue.js design system and component library
  • and thousands more...
---

Roadmap

  • Parse and convert Hex, RGB(A), HSL(A), HSV(A)
  • Saturate, desaturate, grayscale
  • Trim an input value
  • Clamp input numbers to resolve edge cases (e.g. rgb(256, -1, 999, 2))
  • brightness, isDark, isLight
  • Set and get alpha
  • Plugin API
  • 4 and 8 digit Hex
  • lighten, darken
  • invert
  • CSS color names (via plugin)
  • A11y and contrast utils (via plugin)
  • XYZ color space (via plugin)
  • HWB color space (via plugin)
  • LAB color space (via plugin)
  • LCH color space (via plugin)
  • Mix colors (via plugin)
  • CMYK color space (via plugin)
Comments
  • New API to get the color format used to create the colord instance

    New API to get the color format used to create the colord instance

    I recently migrated from tinycolor2 after discovering this awesome library πŸ˜„. However, your library is currently missing a similar API to tinycolor2's getFormat method , which returns the color format used to create the tinycolor instance. I found this API extremely useful when I try to parse user-inputted color code strings.

    It would be great if there is a similar API in your library. For example:

    var color = colord("#ff0000");
    color.getFormat();  // "hex"
    
    color = colord({ r: 139, g: 200, b: 208, a: 1 });
    color.getFormat();  // "rgba"
    

    Thank you very much!

    opened by AnsonH 23
  • ERR_PACKAGE_PATH_NOT_EXPORTED error from colord

    ERR_PACKAGE_PATH_NOT_EXPORTED error from colord

    I'm unable to build my app due to an error coming from a dependency that relies on Colord. Any help with this would be appreciated!

    When running npm run build, I get the following error:

    Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './plugins/names' is not defined by "exports" in ./node_modules/colord/package.json
    
    opened by bildungsroman 21
  • deltaE00 implementation

    deltaE00 implementation

    There is the DeltaE2000 implementation. It works correctly, the results were tested here.

    But we have a problem. Despite the calculations are correct, we have wrong values, just a bit, but always wrong. I spend a lot of time trying to find out why and I found the problem. I was testing LAB / LAB comparison and I found out that if you create Colord instance using LAB color, and get LAB object back - values won't be the same.

    Here the test that is unsuccessful:

    expect(round(colord({ l: 28, a: 50, b: 64 })
      .deltaE00({ l: 33, a: -10, b: 98 }), 5))
       .toBe(37.81158); // result is 35.65174
    

    I took these LAB values to get LAB object back and go this:

    colord({ l: 28, a: 50, b: 64 }) // -> { l: 28.27, a: 50.61, b: 42.13 }
    colord({ l: 33, a: -10, b: 98 }) // -> { l: 33.56, a: -6.01, b: 40.81 }
    

    Now testing these values I have successfull test case:

    expect(round(colord({ l: 28.27, a: 50.61, b: 42.13 })
      .deltaE00({ l: 33.56, a: -6.01, b: 40.81 }), 5))
      .toBe(35.65174);
    

    I think the problem is with discrete values of the RGB color we use to store the color state. Having discrete values as the main state we have discrete values for all the color models and we lost some accuracy.

    If I do something wrong, please tell me, I don't quite sure if I am doing everything correct. In case if the problem is real, I think we should return integer RGB values to the end consumer and use float values for model transformations.

    P.S. The docs is not ready yet in this PR. Will do, but I don't think we need them yet.

    opened by EricRovell 12
  • plugin/monochromatic

    plugin/monochromatic

    I think it would be really useful to have an ability to generate monochromatic colors (tints, shades, and tones). You mentioned usefulness of it in #63 and it was on my list of future proposals.

    I have already working implementation, it looks like this:

    color.tints(5); // generates 5 tint instances of original color;
    color.shades(5); // generates 5 shade instances of original color;
    color.tones(5); // generates 5 tone instances of original color;
    

    During the prototyping, I have got some questions regarding the API:

    1. Should it be one method with type of palette as the parameter like color.monochromatic("tones", 5) or to be a separate methods for each type? I think it would be more readable for this particular case to have different methods.
    2. Should be the original color included and for example, pure white / pure black to tints and shades? It looks like it is a good idea to include them, but the problem arises with the steps parameter, it gets not so understandable. For example, user wants 3 shades and gets: original color, shade, black. Don't look good.

    I would like to hear you ideas and suggestions.

    opened by EricRovell 11
  • CommonJS exports

    CommonJS exports

    While it’s a very progressive approach to only offer ESM exports, I think that CommonJS should be supported too via package entry points, e.g. when used in files ran by Node (e.g. for color manipulation inside tailwind.config.js).

    One of my more recent projects offer the following entry points as an example: https://github.com/kripod/otion/blob/18eea38e49d92c86ff8144fecc6404ebac0fa3ac/packages/otion/package.json#L24-L39

    opened by kripod 10
  • The first concept

    The first concept

    It's been a long time, @molefrog @rschristian!

    I decided to use our experience from react-colorful to create a new color conversion and manipulation tool. It's called colord (🎨Color + πŸ‘‘Lord).

    Actually, the color tool market is quite crowded already, but several packages have most of the market: https://www.npmjs.com/package/color-convert (37M downloads weekly) β€” 13 KB, has 1 dependency https://www.npmjs.com/package/color (11M downloads weekly) β€” 22.4 KB, has 2 dependencies https://www.npmjs.com/package/tinycolor2 (3M downloads weekly) β€” 14,4 KB

    The idea is to create a tool that will support most of their features but will be better, lighter, faster, and TS-oriented.

    This PR is the first concept that I would like to share with you to hear your thoughts.

    The API is going to be similar to tinycolor2's one and the library won't be tree-shakeable (like all popular color conversion tools).

    import colord from 'colord'
    colord("#F00").grayscale().toRgbaString() // "rgba(128, 128, 128, 1)"
    
    

    Tinycolor2 is not the most popular color tool, but I like their API. It's pretty simple to understand.

    Why I'm not going to create a tree-shakeable library? Because nobody likes them. Example: I know 2 tree-shakeable color conversion tools: https://www.npmjs.com/package/color-fns https://www.npmjs.com/package/@swiftcarrot/color-fns Just 2k downloads weekly just because nobody wants to dig into color models and do extra work. Only geeks like me can use libraries of this kind =)

    rgbaToHex(grayscale(parseRgba(rgba))) // the code nobody wants to write
    magick(rgba).grayscale().toHex() // the cope people like
    

    So I think our way is to copy the API of the popular libraries (it means to be not tree-shakeable), but make the library faster/lighter, and provide better DX.

    Current bundle size: 3KB min, 1.14 KB gzip.

    Any feedback is welcome ❀️

    opened by omgovich 10
  • New plugin: A11y

    New plugin: A11y

    Closes #11

    A plugin adding accessibility and color contrast utilities. Strictly follows Web Content Accessibility Guidelines 2.0.

    • [x] color.luminance() [0-1]
    • [x] color1.contrast(color2 = '#ffffff') [1-21]
    • [x] color1.isReadable(color2 = '#ffffff', level = 'AA') β€” alias for color1.contrast(color2) >= 4.5 | 7.

    See updated README for more details, links and examples.

    opened by omgovich 9
  • Color perceived difference

    Color perceived difference

    Hi, it is me again :)

    Found out about color perceived difference and I was thinking, would it be a good addition for colord? Seems like it could be used to extend the LAB plugin.

    opened by EricRovell 7
  • Support approximative color to name

    Support approximative color to name

    When parsing to name using the plugin, if the color is not exactly the right value the result is undefined. At user level, it can be expected that the library always return a color name.

    colord("#ff0000").toName(); // => red
    colord("#fe0000").toName(); // => undefined
    

    If failing to find a perfect match, the lib could search for the closest color. This behavior could also be activated by a parameter to the toName function.

    opened by GMartigny 6
  • Plugin/mix-extended

    Plugin/mix-extended

    Extending the functionality of mix plugin by generating mixtures of colors such as tints, shades, and tones with .tones(colors = 5), .shades(colors = 5), and .tones(colors = 5) methods respectively.

    opened by EricRovell 5
  • Exports map in package breaks when using with vite

    Exports map in package breaks when using with vite

    When trying to import colord with Vite (via Sveltekit), the bundler throws the following error:

    import { colord } from 'colord';
    
    Internal server error: Missing "./package.json" export in "colord" package
    

    Not entirely sure what's going on but on the surface of it it looks like Vite requires access to the package's package.json for analysis, and since it's not exposed via exports it's throwing an error

    opened by madeleineostoja 4
  • Incorrectly parse hexa to rgba to hexa

    Incorrectly parse hexa to rgba to hexa

    actual:

    const expectValue = '#cc88'
    colord(colord(expectValue).toRgbString()).toHex() !== expectValue // #cccc8887
    

    expect:

    const expectValue = '#cc88'
    colord(colord(expectValue).toRgbString()).toHex() !== expectValue // toHex() return value should equal to expectValue
    
    opened by MrKou47 0
  • a11y does not support opacity

    a11y does not support opacity

    The a11y plugin doesn't support opacity. It would be great if it did.

    Black on white = 21
    colord('#000000').contrast('#FFFFFF')

    Transparent black on white = 21, even though the text is invisible.
    colord('#00000000').contrast('#FFFFFF')

    Black on white is readable
    colord('#000000').isReadable('#FFFFFF')

    Transparent black on white is readable, even though the text is invisible.
    colord('#00000000').isReadable('#FFFFFF')

    opened by dasveloper 0
  • feat: implement `relative` option for lighten/darken manipulation

    feat: implement `relative` option for lighten/darken manipulation

    #90 issue has a valid point: the relative lightness manipulation has a lot of sense.

    At first I thought it should be the default behavior, still, as it may be a breaking change, I implemented the feature as an optional relative: Boolean parameter.

    opened by EricRovell 1
  • Relative lighten/darken

    Relative lighten/darken

    I replaced color with colord in my project, but found out I don't get the same results, because they treat lighten() and darken() differently: While color shifts color by a fraction of itself, while colord shifts color by a fraction of whole spectrum.

    I prototyped this wrapper to implement this functionality:

    import { AnyColor, Colord, HslaColor } from 'colord'
    import { colord as nativeColord } from 'colord'
    
    export const clamp = (number: number, min = 0, max = 1): number => {
      return number > max ? max : number > min ? number : min
    }
    
    export const lightenRelative = (color: AnyColor | Colord, amount: number): HslaColor => {
      const hsla = nativeColord(color).toHsl()
    
      return {
        h: hsla.h,
        s: hsla.s,
        l: clamp(hsla.l * (1 + amount), 0, 100),
        a: hsla.a
      }
    }
    
    class ExtendedColord extends Colord {
      public lightenRelative(amount: number = 0.1) {
        return extendedColord(lightenRelative(this.rgba, amount))
      }
    
      public darkenRelative(amount: number = 0.1) {
        return extendedColord(lightenRelative(this.rgba, -amount))
      }
    }
    
    export const extendedColord = (input: AnyColor | Colord): ExtendedColord => {
      if (input instanceof ExtendedColord) return input
      return new ExtendedColord(input as any)
    }
    

    and I will use it for now, but I'd prefer to merge it into the library itself - are you interested in this functionality? I would love to make a PR if so.

    Thank you πŸ™

    opened by michal-kurz 6
  • Add P3 and Rec.2020 gamut support

    Add P3 and Rec.2020 gamut support

    Lab and OKLab can be used to generate colors outside sRGB space. We need methods to control it:

    1. Method to check that current colors is in sRGB, P3, or Rec.2020 space.
    2. If the color is outside, we need a method to convert color to closest color in necessary color space

    See also:

    opened by ai 0
Releases(v2.9)
  • v2.9(Oct 18, 2021)

    • New minify plugin adding color string minification utilities.
    import { colord, extend } from "colord";
    import minifyPlugin from "colord/plugins/minify";
    
    extend([minifyPlugin]);
    
    colord("black").minify(); // "#000"
    colord("#112233").minify(); // "#123"
    colord("darkgray").minify(); // "#a9a9a9"
    colord("rgba(170,170,170,0.4)").minify(); // "hsla(0,0%,67%,.4)"
    colord("rgba(170,170,170,0.4)").minify({ alphaHex: true }); // "#aaa6"
    
    Source code(tar.gz)
    Source code(zip)
  • v2.8(Sep 23, 2021)

    • @EricRovell added delta method to calculate the perceived color difference (CIE Delta E 2000) between two colors. The return value is 0 if the colors are equal, 1 if they are entirely different.
    colord("#faf0c8").delta("#ffffff"); // 0.148
    colord("#3296fa").delta("#197dc8"); // 0.099
    colord("#afafaf").delta("#b4b4b4"); // 0.014
    colord("#000000").delta("#ffffff"); // 1
    
    Source code(tar.gz)
    Source code(zip)
  • v2.7(Aug 27, 2021)

    • @EricRovell added new tints, tones and shades methods to mix plugin.
    const color = colord("#ff0000");
    color.tints(3).map((c) => c.toHex());  // ["#ff0000", "#ff9f80", "#ffffff"];
    color.shades(3).map((c) => c.toHex()); // ["#ff0000", "#7a1b0b", "#000000"];
    color.tones(3).map((c) => c.toHex());  // ["#ff0000", "#c86147", "#808080"];
    
    Source code(tar.gz)
    Source code(zip)
  • v2.4(Jul 23, 2021)

    • @EricRovell added a new plugin to perform harmony colors generation.
    import { colord, extends } from "colord";
    import harmoniesPlugin from "colord/plugins/harmonies";
    
    extend([harmoniesPlugin]);
    
    const color = colord("#ff0000");
    color.harmonies("analogous").map((c) => c.toHex()); // ["#ff0080", "#ff0000", "#ff8000"]
    color.harmonies("complementary").map((c) => c.toHex()); // ["#ff0000", "#00ffff"]
    color.harmonies("rectangle").map((c) => c.toHex()); // ["#ff0000", "#ffff00", "#00ffff", "#0000ff"]
    color.harmonies("split-complementary").map((c) => c.toHex()); // ["#ff0000", "#00ff80", "#0080ff"]
    color.harmonies("tetradic").map((c) => c.toHex()); // ["#ff0000", "#80ff00", "#00ffff", "#8000ff"]
    color.harmonies("triadic").map((c) => c.toHex()); // ["#ff0000", "#00ff00", "#0000ff"]
    
    Source code(tar.gz)
    Source code(zip)
  • v2.2(Jul 18, 2021)

    • @EricRovell added a new plugin to perform CMYK conversions
    import { colord, extend } from "colord";
    import cmykPlugin from "colord/plugins/cmyk";
    
    extend([cmykPlugin]);
    
    colord("#ffffff").toCmyk(); // { c: 0, m: 0, y: 0, k: 0, a: 1 }
    colord("#999966").toCmykString(); // "device-cmyk(0% 0% 33% 40%)"
    colord({ c: 0, m: 0, y: 0, k: 100, a: 1 }).toHex(); // "#000000"
    colord("device-cmyk(0% 61% 72% 0% / 50%)").toHex(); // "#ff634780"
    
    Source code(tar.gz)
    Source code(zip)
  • v2(May 21, 2021)

    • CSS Color Level Specifications are now strictly followed by library parsers.
    // missing hex prefix
    colord("aabbcc").isValid() // false
    
    // mixing numbers and percentages is not allowed in CSS
    colord("rgb(50%, 50, 50%)").isValid() // false
    
    // missing comma
    colord("rgb(50%, 50 50%)").isValid() // false
    
    // missing bracket
    colord("rgb(10 10 10").isValid() // false
    
    // mixing comma and slash syntaxes is not allowed
    colord("rgba(10, 50, 30 / .5)").isValid() // false
    
    // missing percent sign for saturation and lightness
    colord("hsl(10deg, 50, 30)").isValid() // false
    
    Source code(tar.gz)
    Source code(zip)
  • v1.7(May 11, 2021)

  • v1.6(May 7, 2021)

  • v1.5(May 3, 2021)

  • v1.4(Apr 28, 2021)

  • v1.3(Apr 25, 2021)

  • v1.2(Apr 16, 2021)

  • v1.1(Apr 14, 2021)

  • v1.0(Apr 14, 2021)

    The fastest and tiniest color manipulation library is officially live!

    • πŸ“¦ Small: Just 1.4 KB gzipped (3x+ lighter than color and tinycolor2)
    • πŸš€ Fast: 2x+ faster than color and tinycolor2
    • 😍 Simple: Chainable API and familiar patterns
    • πŸ’ͺ Immutable: No need to worry about data mutations
    • πŸ›‘ Bulletproof: Written in strict TypeScript and has 100% test coverage
    • πŸ—‚ Typed: Ships with types included
    • πŸ— Extendable: Built-in plugin system to add new functionality
    • πŸ‘« Works everywhere: Supports all browsers and Node.js
    • πŸ’¨ Dependency-free
    Source code(tar.gz)
    Source code(zip)
Owner
Vlad Shilov
Frontend Engineer at resume.io πŸ‘¨β€πŸ¦³ ex-CTO πŸ¦† Rubber duck hunter πŸ›  Micro-libraries developer πŸ“’ HolyJS Conf program committee member
Vlad Shilov
Hemsida fΓΆr personer i Sverige som kan och vill erbjuda boende till mΓ€nniskor pΓ₯ flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo fΓΆr kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Tool Cool Color Picker is a color picker library written in typescript and using web component technologies.

Tool Cool Color Picker Tool Cool Color Picker is a color picker library written in typescript and using web component technologies. Check out the demo

Tool Cool 13 Oct 23, 2022
A minimal yet powerful HTTP client/API testing tool made for speed.

req req is a lightweight, minimal yet powerful HTTP client slash API testing tool designed for speed. Contents Features Installation Documentation Con

Siddharth 37 Aug 29, 2022
zieeco 12 Jul 8, 2022
Change the color of an image to a specific color you have in mind.

image-recolor Run it: https://image-recolor.vercel.app/ image.recolor.mov Acknowledgments Daniel BΓΌchele for the algorithm: https://twitter.com/daniel

Christopher Chedeau 21 Oct 25, 2022
A little toy app to help you find the nearest match for a given color within a Figma Tokens color palette.

Hey Palette So you've got a color palette in Figma and you've used the Figma Tokens plugin to export that palette to JSON. Let's say you have a color

Kalo Pilato 5 Nov 15, 2022
Colr Pickr, a vanilla JavaScript color picker component built with SVGs, with features like saving colors. Similar design to the chrome-dev-tools color picker.

Colr Pickr Colr Pickr, a vanilla JavaScript color picking component built with SVGs, with features like saving colors. Similar design to the chrome-de

TEK 27 Jun 27, 2022
A NodeJS package to convert any RGB color to HEX color or viceversa. Also supports HSL conversion.

Unhex ?? A NodeJS package to convert any RGB color to HEX, HSL color or viceversa. Example div { color: #fff; background-color: #0070f3; } After r

Arnau Espin 2 Oct 1, 2022
This is a simple yet powerful to-do list app. It allows the user to add, remove, edit and check a task as completed.

To-Do-List App In this project, I made a simple website called To-do-List. The user is able to add and remove tasks, mark them as done or undone, the

Tracy Musongole 8 Dec 27, 2022
Simple yet powerful to-do list app to manage your daily tasks! Built with: CSS, HTML, JavaScript

To-Do List Simple yet powerful to-do app to manage your daily tasks! Built With HTML, CSS Fameworks: N/A Technologies: Linters, Git, GitHub, Webpack L

Amaury Permer 7 Jul 21, 2022
High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.

lazysizes lazysizes is a fast (jank-free), SEO-friendly and self-initializing lazyloader for images (including responsive images picture/srcset), ifra

Alexander Farkas 16.6k Jan 1, 2023
AppRun is a JavaScript library for developing high-performance and reliable web applications using the elm inspired architecture, events and components.

AppRun AppRun is a JavaScript library for building reliable, high-performance web applications using the Elm-inspired architecture, events, and compon

Yiyi Sun 1.1k Dec 20, 2022
πŸ”‘ Keagate is an open-source, high-performance alternative to popular cryptocurrency payment gateways such as Coinbase Commerce, CoinGate, BitPay, NOWPayments, CoinRemitter, CoinsPaid and more.

⛩️ Keagate – A High-Performance Cryptocurrency Payment Gateway ?? This project is actively in development ?? Table of Contents About the Project Purpo

null 76 Jan 3, 2023
An ultra-high performance stream reader for browser and Node.js

QuickReader An ultra-high performance stream reader for browser and Node.js, easy-to-use, zero dependency. Install npm i quickreader Demo import {Quic

EtherDream 156 Nov 28, 2022
A scalable, high-performance feature management and progressive experimentation platform

Introduction & Our Philosophy FeatBit is a scalable, high-performance Feature Management and Progressive Experimentation platform. Feature Management

null 345 Jan 1, 2023
High performance personalization & a/b testing example using Next.js, Edge Middleware, and Builder.io

Next.js + Builder.io Personalization & A/B Testing with Edge Middleware This is a fork of Next.js Commerce with Builder.io integrated and using Edge M

Builder.io 7 Sep 6, 2022
High performance JSX web views for S.js applications

Surplus const name = S.data("world"), view = <h1>Hello {name()}!</h1>; document.body.appendChild(view); Surplus is a compiler and runtime to all

Adam Haile 587 Dec 30, 2022