Color-Description is a class that turns a technical color representation into a human readable description.
npm install color-description
import ColorDescription from "color-description/dist/index.esm";
const cd = new ColorDescription("#0a4a7a");
cd.nouns;
// ["blue", "navy"]
cd.descriptiveWords;
// ["deep", "rich", "dark", "dim", "somber", "matte", "dusty", "ashy",
// "unsaturated", "cold", "cool", "blue", "blueish", "navy"]
cd.getDescriptiveList(false, 2);
// "deep and rich"
cd.color = "#e0b830";
cd.nouns;
// ["yellow", "gold"]
cd.getDescriptiveList(false, 3);
// "rich, golden and warm"
cd.meanings;
// ["enthusiasm", "opportunity", ...]
cd.effects;
// ["stimulate", "relax", ...]
cd.usage;
// ["sale", "cheap", "budget", ...]The order of the words matters. Both nouns and descriptiveWords are sorted from the best fit to the loosest one:
nouns[0]is the name most people would give the color.#0a4a7ais "blue" first and "navy" second; a colour can also be "grey" first and "blue" second when the tint is faint.descriptiveWords[0]is the single adjective that best describes the shade:deepfor a dark saturated blue,coolfor a faintly tinted grey,richfor a gold,brightfor a turquoise at the gamut edge. The words after it are secondary: still true, but less specific.
So descriptiveWords[0] + " " + nouns.join(" ") gives a short, sensible name ("deep blue navy", "cool grey blue", "rich yellow gold"), and getDescriptiveList(false, n) gives the n most fitting adjectives as a sentence fragment. Ask for getDescriptiveList(true) only when you want a random order.
The default dataset is written in English, and its meanings, effects, and usage labels are subjective and written from a western perspective: English dataset
Interpretation model used by the dataset:
meaningsare symbolic associationseffectsare perceptual or behavioral effectsusageis contextual fit such as industries, themes, and applications
color(string | object): a color in any CSS syntax: named colors, hex,rgb(),hsl(),hwb(),lab(),lch(),oklab(),oklch()andcolor(display-p3 ...), or a culori color object. Wide-gamutcolor()spaces such asa98-rgborprophoto-rgbare not registered and throw. Colors outside sRGB are described as their most saturated in-gamut equivalent.words(object, optional): a word dataset in the shape ofsrc/en.js; defaults to the English one
color: get or set the current colornouns: color names, best fit first (["blue", "navy"])descriptiveWords: adjectives, best fit first (["deep", "rich", "dark", ...])description: a short paragraph about the color familymeanings: symbolic or emotional associationseffects: typical effects or signals the color can createusage: contexts, industries, themes, or applications where the color fitstemperatureWords: the closest correlated color temperature,{ value: 1800, descriptive: ["ultra warm"] }bestContrast:"black"or"white", whichever has the higher WCAG contrast on this colorformats: the parsed color inrgb,hsl,oklch,okhslandcmyk
getDescriptiveList(random?, limit?): the descriptive words joined into a phrase ("deep, rich and dark").limitkeeps the first n words, which are the best fitting ones;randomshuffles them firstpercentages(model?): channel values of the color as fractions, for"rgb"(default),"hsl"or"cmyk"percentageWords(model?): those channels described in words (["a good bit of", "a good bit of", "a little bit of"])
This package supports multiple module formats, each about 67 KB minified with the dataset and a tree-shaken culori bundled in:
- ESM (modern):
dist/index.esm.js - CommonJS (Node.js):
dist/index.cjs - IIFE (browser, global
ColorDescription):dist/index.iife.js
# Build all formats
npm run build
# Run tests
npm run test
# Development with watch mode
npm run devAll color matching is performed in OKLCH color space, which provides perceptually uniform lightness, chroma, and hue — unlike HSL where identical saturation/lightness values can look dramatically different across hues.
Color names are fitted to ~184,000 English-language responses from the Many Languages, Many Colors survey. For every point of a grid over the sRGB gamut in OKLCH, the names given to the nearest survey responses are counted; each entry in src/en.js covers the region where its name is the most common answer, or a close second. That is why a hue alone never names a color here: a dark muted yellow is olive, a pale red is pink, a muted mid-light orange is brown, a dark cyan is teal, and low-chroma colors are grey or black first.
The nouns are the names people actually used: red, orange, yellow, green, blue, purple, pink, brown, black, white and grey as the basic terms, then maroon, beige, peach, salmon, gold, olive, lime, mint, teal, turquoise, cyan, sky blue, navy, periwinkle, indigo, lavender, violet, magenta, plum and mauve where they are common enough to win or come second in the vote. Synonyms with the same region (burgundy, mustard, aqua, lilac, fuchsia) appear as descriptive words rather than separate nouns.
The adjectives are ordered the same way. The character words in src/en.js (pure, very dark, deep, dark, warm and cool for faint tints, pale, pastel, light, bright, muted, soft, medium, rich, vivid) are listed by priority, and the first entry whose region contains the color supplies descriptiveWords[0]; every later match only adds secondary words. Greyishness is judged on absolute OKLCH chroma, but vividness is judged on okhsl saturation, the chroma relative to what sRGB can show at that lightness and hue: a turquoise at the gamut edge is "bright" although its absolute chroma is small, and a darkened yellow is "muted" or a "rich gold" rather than vivid. Each region was checked by eye on a sheet of swatches per hue.
node tools/testbench.mjs renders the whole grid as an HTML page (tools/testbench.html) with the library's names next to the survey vote for each swatch, for checking by eye. tools/survey-fit.mjs and tools/survey-finemap.mjs rebuild tools/survey-labels.json from the raw survey file.
Kim, Y., Thayer, K., Gorsky, G. S., & Heer, J. (2019). Color Names Across Languages: Salient Colors and Term Translation in Multilingual Color Naming Models. EuroVis 2019. Project repository
MIT