home about me

colornamify

A library for assigning human-readable names to colors, and an accompanying Visual Studio Code extension.

npm install colornamify

TL;DR

Input color object, receive string.

Put cursor on color, receive name suggestion.

The Problem

As the old joke goes, there are only two hard problems in computer science: Naming things, cache invalidation and off-by-one errors. colornamify aims to alleviate problem[0] for the scope of colors.

The Solution

colornamify has a list of RGB values, assigned to currently 6691 unique color names. Provided with a color object, the library will return the name of the closest match.

Names have been scraped from various sources - Wikipedia, Crayola Crayon Colors, Resene Paints, color dictionaries and US Federal Specifications. See the comments in colors.js for more information.

Since the goal of this library is coming up with names and not identifying colors, names are not guaranteed to match the color values of their sources. Duplicate colors have been slightly spread around instead of deleted, to increase the dataset.

Use Case

As Landon Schropp has already outlined on David Walsh’ Blog, the perfect system of naming color variables in Sass is not obvious.

If you’re building a design framework where your goal is covering a wide ground of shades and hues, the approach used by Materialize.css might be fine and dandy. They use a handful of base colors - red, pink, purple, and so on - and add pre-defined modifiers, with numbers denoting their strength. This results in red lighten-3 or pink darken-5 or purple accent-1. Great for covering ground, practical if you get to define the colors used, easy to automate.

In my daily life as a frontend developer, that’s rarely working, though. Most of the time, I’m tasked with implementing a design - delivered as a Photoshop file, a JPEG, Sketch file, scribbled with crayons on a dirty napkin, you name it - into a working web application. This design will have a (limited) color palette, but it’s not always provided as such. First, I’ll define all colors used in the project:

// 01_settings/_colors.scss
$color-cyan: #2793d0;
$color-cyan-dark: #2c5578;
$color-cyan-light: #0ac9f8;

Assign those colors to component variables:

// 01_settings/_components.scss
$badge-textColor-hover: $color-cyan-light;
$box-borderColor: $color-cyan-dark;
$link-textColor: $color-cyan;

And use them in the components:

// 05_components/box.scss
.c-box {
  border: 1px solid $box-borderColor;
  // …
}

So far, so good. But in cases where the palette is not cleanly provided by the designers - or colors are used that are not in the palette - we might find out we need another color at a later point. What if we find out we need to add #076aa3 later on? It’s darker than $color-cyan, but lighter than $color-cyan-dark. Are we going with $color-cyan-halfdark now? $color-cyan-dark-but-more-saturated? Rename the existing variable to $color-cyan-darker and update the whole codebase? Not good.

Using colornamify, the whole coming-up-with-good-names process is easier:

// 01_settings/_colors.scss
$color-curiousblue: #2793d0;
$color-sanjuan: #2c5578;
$color-vividskyblue: #0ac9f8;
$color-sapphireblue: #076aa3;

Possible Improvements

Aside from adding more colors, one possible area of improvement would be performance. Looking up 1,000 randomly generated color codes takes 1,100ms on my MacBook Air 2018’s 1.6GHz i5 - that’s not bad, but there’s always faster, right?

colornamify treats the RGB colors as points in a 3D space, looking for the entry with the shortest distance to the color being looked up. It uses a naïve lookup algorithm, simply iterarting through all points, looking for the shortest one.

Lookups are cached. To save on performance, only the squared distance is calculated; since it’s only used for comparison, there’s no need to get the square root. If there’s a direct match, iteration is stopped. Worst-case complexity for this is at O(n).

A possible solution to increase performance would be calculating the shortest delta Δ (distance between points) of the set and finish the search if the currently checked distance is half or less of the shortest - we have already found the closest match possible. But since lowest Δ of the colornamify set is at 1, there’s no performance increase to be gained from this.

In 3 dimensional space (our RGB color space), using a k-d tree would increase search performance. Such a tree could be generated at compile time, and with the only operation run on it being the nearest neighbor search, we’d get a complexity somewhere around O(log n). Way better.

As for precision, instead of the RGB model a weighted HSL model could be used, to prioritize human perceived nearest color neighbors over mathematic nearest neighbors.