Generating color scales for design systems
With little effort, you can find abundant examples of how colors have been named. HTML5 and CSS3 color specifications name 140 colors. Crayola names 135 standard crayon colors. Wikipedia lists hundreds of colors, with undeclared citations. ColorHexa lists 746 color names. Users have named close to 8 million colors on COLOURlovers. There are even research projects which attempt to resolve the inconsistencies among various color dictionaries.
Naming colors is quite an art in itself, but I’m more interested in how to name variations of a single primary color. For at least Web application design, it’s probably best to be conservative when applying colors, keeping to a palette of a few colors with various tints and shades. Too many colors results in a confusing visual language, while a more considered set of colors should help to clarify the interface. In this way, I want to explore helpful ways to consistently codify a controlled set of colors to assist both designers and developers in their practice.
Google Material Design color palette uses a 10-point scale of 50 to 900, with 50 being the lightest tint, 900 being the darkest shade, and 500 representing the primary color. They also introduce an almost neon-like A-series for most colors (A100, A200, A400, and A700), although they don’t elaborate on how or why to use those variations.
PANTONE uses numbering systems in a variety of ways to codify either the color family or where the color is located within their print materials. However, that shallow explanation fails to describe the methods of how they map color families to particular numbers. One can roughly interpret a pattern of shifting hues to their 3-digit numbers, but the 4-digit numbers tend to become much less comprehensible.
font-weight property shares a similar scale to that of Material Design. A lighter and thinner font weight starts at
100, graduating in heaviness in 100-point increments until
400 maps to a normal weight, while
700 maps to a traditionally bold weight.
CSS frameworks, such as Bootstrap and Foundation, tend to sidestep the problem by creating derivatives from primary colors using color functions. Relying on these functions, however, supposes that if the source color should change, the percentages of, e.g., lightness and darkness may need to be adjusted in turn. While it’s easy to keep colors as derivatives by using color variables, it can result in a problem in which there are too many derivatives, if they are managed locally instead of in a shared source file.
For example, rather than defining colors during their use:
You should centralize all color declarations:
Goals for codification
Taking these exemplars into consideration, a new scale for codifying colors should support the following goals:
- Scales should support granularity.
- Scales should be able to be generated from any color.
- Points along the scale should share a common meaning.
Supporting Goal #1 is accomplished with setting a number range. The range of
1000 provides an abundant of initial possibilites, along with being consistent with Material Design and the
font-weight specification. This range could always be tightened later, as needed.
Material Design anchors its scale in the middle with primary colors, designated with a
500 marker. This approach supposes that color was perhaps chosen first, and then an evenly distributed series of tints and shades were subsequently derived. In order to support Goal #2, the primary source color should be able to reside anywhere along the range, not just the middle, and appropriate tints and shades could still be derived.
Similar to Material Design, the point along the scale should correspond to the lightness or darkness of a color. If
0 is always pure white (
1000 is always pure black (
#000), then to support Goal #3, the steps along the scale should roughly correspond to their equivalent lightness value.
Alas, lightness is a tricky subject that requires an understanding of color spaces to properly define it. Digital designers should be quite familiar with RGB, at least for the sake of using hexadecimal color values in CSS. Designers may also be familiar with another family of hue-saturation-* color spaces, which includes HSL (hue-saturation-lightness), HSV (hue-saturation-value), HSB (hue-saturation-brightness), and HSI (hue-saturation-intensity). These are attempts to represent the RGB model in a form that is easier to approach and reason about. While the lightness, value, brightness, and intensity values are easy to conceptualize, they ultimately are models describing how computers render color, and therefore, they’re insufficient to inform us how humans would perceive a given color. Colors may share identical lightness values, yet their perceived brightness is probably different. The Lab color space resolves this issue, given its
L* (lightness) value approximately corresponds to perceived brightness. A
L* value of
0 is the darkest black, while a value of
100 represents the brightest white.
Naming color variables
Each color variable name consists of three parts:
- namespace labeled as
colorto indicate the variable is a color;
- color scale to group the color derivatives;
- point to indicate the location of the derivative along the scale.
Put together, the template for a Less color variable name would follow this pattern:
In practice, we could describe an abbreviated color scale in this way:
Generating color scales
Using Chroma.js, we can interpolate any color within our scale. For this example, the scale will be seeded with white, green, and black colors.
Bezier interpolation will ease the blending of the colors, while lightness correction will ensure a linear lightness progression throughout the scale. Run the following Node script to generate the nine-point color scale.
The color scale is generated as Less variables. However, with little tweaking, the output could be adapted as desired to better conform to other contexts.
For those desiring a visual editor rather than running a custom Node script, the Chroma.js Color Scale Helper tool is an excellent alternative to quickly experiment with various color scale configurations.
We demonstrated it is very possible to consistently devise color scales, linearly graduating from light to dark. By codifying the scale based on perceived brightness, we have a normalized way to compare colors across any scale, and it can simplify how we choose colors.
From here, there are several more tools and features that could be created to assist designers and developers interested in using codified color scales:
- Publish a
npmpackage to codify color scales.
- Create a visual editor for codifying color scales, similar to the Chroma.js Color Scale Helper.
- Allow the source color to be retained and placed within the generated scale, instead of the scale merely being seeded by it.
- The output from these tools should be highly tailorable, and the output should not be bias toward any tangental tool; for example, its usefulness would be severely limited if it only is compatible with Less variables.