Lunaria
Lunaria is a family of soothing, moderate-contrast color palettes for terminals, text editors, and technical documentation. Lunaria's colors were generated algorithmically, employing the cutting edge of color science: the CAM16 color appearance model and its associated uniform color space and chromatic adaptation transform. Lunaria includes three distinct palettes:
- The Light palette is for users who prefer to read dark text on a light background. It is designed to provide the best facsimile of ink-on-paper that an LCD monitor can possibly achieve. Its colors are optimized for viewing in the bright window-lit conditions typical of 21st century office buildings, but hold up well in a broad range of conditions.
- The Dark palette is for users who prefer light text on a dark background. Its neutral colors are designed to give an impression of a moonlit night and are derived from actual spectral data collected from the Fred Lawrence Whipple mountaintop astronomical observatory. It is optimized for nighttime viewing under dim, warm LED illumination.
- The Eclipse palette is almost identical to the Dark palette, but optimized for the same brighter viewing conditions as the Light palette is. The most visible difference is that the background is darker as a result of compensating for increased viewing flare (ambient light reflected off the monitor surface).
Every palette contains 55 colors, with role-descriptive names like deëmphasized foreground, soft red, terminal low green, and background blue. Each palette uses the same names, even though the colors denoted by those names differ. This makes life easy for designers: Once you've created a web page or editor theme using one Lunaria palette, the other palettes are a string substitution away.
Palette structure
A Lunaria palette consists of seven neutral colors, seven groups of six foreground chromatics (all based on the same six hues), and six background chromatics.
Neutrals
NeutralsThe neutral colors each have several aliases. First, they can be named according to their shade — from darkest to lightest: deep black, black, dark gray, medium gray, light gray, white, bright white. Foreground/background combinations for ordinary text are either dark gray on white or light gray on black. Alternatively, the neutrals can be named by their role in either a regular or inverse color scheme. A regular scheme is dark-on-light for the Light palette and light-on-dark for the Dark and Eclipse palettes. In an inverse scheme, these combinations are reversed. The intent is for designers to use a regular scheme for all the main parts of the screen, and an inverse scheme to accent small areas. The following table shows the roles of the neutral colors in each of the two schemes.
Regular scheme | Color | Inverse scheme |
---|---|---|
Emphasized background | — | |
Background | Emphasized foreground | |
Deëmphasized background | Foreground | |
Deëmphasized foreground | Deëmphasized foreground | |
Foreground | Deëmphasized background | |
Emphasized foreground | Background | |
— | Emphasized background |
The terms emphasized and deëmphasized should respectively be understood as “increased contrast” and “decreased contrast”. In the case of background colors, they are somewhat misleading, since any modulation in either direction tends to provide emphasis.
Large headings and other display text should
always be set in the emphasized foreground
color, as the regular foreground color will look
washed-out. Small, boldface text, however, works
about as well in either color. I prefer to use
the regular color for table headings and the
emphasized color for bold body text (e.g.
to style the HTML
<strong>
element). In any
case, use of the emphasized foreground color
should always be complemented by some other form
of emphasis such as large or bold text: it's too
subtle to stand on its own.
You can use alpha-channel transparency to achieve intermediate steps between background colors. The background of the above table is deëmphasized with 50% opacity, resulting in a composite color at the midpoint between regular and deëmphasized.
Foreground chromatics
Foreground chromaticsThere are seven groups of foreground chromatics. Each group contains six colors: a red, a yellow, a green, a blue, a violet, and a magenta. Hues are spaced at regular 1/7 intervals on the CAM16 color wheel, skipping a step at cyan on account of the human eye's poor sensitivity to hue contrast in that region of the spectrum. All groups use the same six hues, while differing in lightness and chromaticity.
We begin by introducing the soft colors:
When using Lunaria for syntax highlighting, the soft colors are your workhorses. Use them for marking basic syntax elements such as string literals when you want to make their lexical status apparent with drawing the eye toward them. All the soft colors have the same lightness as medium gray, so they are equally legible against regular and inverse backgrounds. This equal, medium lightness along with their rather low saturation makes them fungible and devoid of any individual psychological associations. They can be permuted freely with little consequence.
When you need a little more punch, use the vivid or (against an inverse background) inverse vivid colors:
The vivid colors have more individuality than the soft colors. Their higher saturation attaches more cultural baggage to their respective hues. For example, vivid red and vivid yellow are the clear choices for error and warning squiggles. Vivid magenta and vivid blue are appropriate for visited and unvisited hyperlinks. The vivid colors have unequal lightness: in both the regular and inverse schemes, the cooler colors are darker than the warmer ones. All of them have more contrast with the background than the soft colors do.
The high contrast and inverse high contrast colors are for accommodating visually-impaired readers. They are fully as dark or light as their respective neutral foreground. More about these later, in the Accessible Design section.
The final two foreground groups are the low and high terminal colors, intended for theming 16-color ANSI terminals. High and low red, yellow, green, and magenta, and the neutrals black, dark gray, light gray, and white, all map to their eponymous ANSI colors. Lunaria's blues map to ANSI's cyans, and Lunaria's violets map to ANSI's blues.
I'll be honest: These colors are not my favorite part of the palette. Compared to the other foreground groups, they look ugly and chaotic. They must, though, because they're the solution to an ugly and chaotic problem: maintaining readability when the programmers of terminal applications select color combinations that are dubious to begin with and then assume that they will render on everyone else's terminal the same way they render on their own. What makes this particularly difficult is that ANSI colors aren't always foreground colors. Lunaria's other foreground groups — even if you occasionally opt for a “reverse video” effect by using the regular background color as a foreground atop a vivid-colored background — are always contrasted with a small, known set of neutral colors, no matter which may be on top. Nobody in their right mind would put Lunaria vivid green on a vivid blue background; even Medieval armorers knew better than this. But with the ANSI colors, such combinations are all too common, and so we must accommodate them.
The lightnesses of the Lunaria terminal colors are
determined such that their log-luminances (after
accounting for flare) are a linear transformation of
the log-luminances of the
“classic”
ANSI terminal colors (which range from #000000
for black to #ffffff
for white), into
the new range of Lunaria black to Lunaria white.
Since Lunaria's range is narrower, all contrast
ratios become slightly compressed but they remain
essentially intact. For the Light palette, the
target range is actually a little darker: from Lunaria
deep black to 2/3 of Lunaria white. This makes high
yellow readable against a white background.
Background chromatics
Background chromaticsThe background chromatics are useful for marking regions of text, such as clipboard selections, search matches, and insertions and deletions. The six colors are based on the four cardinal hues of the opponent process model, providing yellow/blue and red/green dichotomies that are in some sense psychologically “pure”.
Opaque (100%) | Dodrantopaque (75%) | Semiopaque (50%) | Quadrantopaque (25%) | Octantopaque (12.5%) |
---|
The colors are named background red, background green, background yellow, background blue, background light yellow, and background dark blue. In the Light palette, background light yellow has the alias “background highlight” and background dark blue has the alias “background lowlight”; in the Dark and Eclipse palettes, these aliases are swapped.
The fully-opaque background chromatics are almost always too saturated; the middle three opacities should be used most often. Selected text on this page is quadrantopaque lowlight. Dodrantopaque highlight is a good color for search matches — something which regretably can't be demonstrated here because CSS doesn't support it, but it would look like this.
Accessible Design
Although Lunaria is foremost meant to be enjoyed by readers with normal vision, with a little extra care it can accommodate certain visual impairments as well. In particular, we'll discuss colorblindness and impaired contrast sensitivity.
Lunaria should be fully usable by anomalous trichromats (those with protoanomaly, deuteranomaly, or tritanomaly) without any special consideration on the part of the designer. Any two Lunaria colors easily distinguishable by those with normal vision should remain easily distinguishble with anomalous cones.
Dichromats (those with protanopia, deuteranopia, or tritanopia) will struggle to distinguish some of Lunaria's forgeground colors from each other, and protanopes may struggle to distinguish magenta from gray. Dichromats looking to customize their editor's syntax highlighting should probably look elsewhere. Designers using Lunaria for media that will be consumed by general audiences with an unknown range of disabilities should follow the general best practice of never relying solely on color for conveying important information. Underline your hyperlinks. Yes, it makes them ugly. Do it anyway.
Lunaria's foreground color groups vary in their degree of contrast with the regular background color, and therefore in their suitability for readers with impaired contrast sensitivity. The following table summarizes which parts of the Light palette adhere to various standards that define contrast requirements.
ISO 9241 | WCAG AA | WCAG AAA | |
---|---|---|---|
Soft colors | Yes | If large or bold | No |
Vivid colors | Yes | Yes | If large or bold |
High contrast colors | Yes | Yes | Yes |
Terminal colors | No | No | No |
ISO 9241 sets contrast standards for users with normal vision. WCAG AA is for users with the mild contrast impairment that usually accompanies 20/40 vision, and WCAG AAA is for users with the moderate contrast impairment that usually accompanies 20/80 vision. There is no standard for severe impairment, since such users typically rely on screen readers. WCAG defines “large” text as 14 points or larger and leaves “bold” deliberately undefined.
Both ISO 9241 and WCAG pessimistically assume 5% flare for computing contrast ratios; this is higher than what any of the Lunaria palettes are optimized for. Under better viewing conditions, the Dark and Eclipse palettes meet the same contrast thresholds as is asserted for the Light palette in the table above, but at 5% flare they do not, so these palettes can be considered to comply with the spirit but not the letter of the ISO and WCAG recommendations. Note that sites can claim WCAG compliance as long as some “conforming alternate version” satisfies all its requirements, so even a strict reading of WCAG does not forbid you from making the Dark and Eclipse palettes available as long as the Light palette is available as well and you restrict yourself to the compliant color groups.
Although Lunaria's terminal colors do not consistently meet any standard for contrast, users with impaired contrast sensitivity should investigate Hyper, a terminal emulator which includes a contrast-enhancement feature. When Hyper encounters a foreground/background combination that does not satsify a user-specified minimum contrast ratio, it will adjust the lightness of the foreground color while preserving its hue.