About hsLab
Graphic design for screens has a unique set of challenges
when it comes to working with colors. There are a few key aspects of a good
color design tool: it must have an intuitive color mixing paradigm, the
lightness/darkness of a color must be accurately represented, and the results
must exportable to the RGB color space. Current tools that work with just a
single color space; for example, RGB, HSL, and LAB, fail to meet all three of
these key aspects. The hsLab tool takes the good parts of working with these
color spaces, and combines them into a better design experience.
This article is written from an exploratory point of view. I'll start with some
basics, and explore why these failures exist, and from where these requirements
arise.
|
RGB Format |
Intuitive Mixing |
Accurate Lightness |
RGB |
✔ |
✖ |
✖ |
HSL |
✖ |
✔ |
✖ |
LAB |
✖ |
✖ |
✔ |
The Problems and Requirements
Starting and ending up with RGB
Screen design is inherently limited to display technology,
and in all cases screens use a Red Green Blue color space to define what color
a pixel will show. So, designers must, at least at some point in their
process, realize their design colors in RGB. This will be our first
requirement: that our tool must output colors in RGB.
Because RGB is required for defining colors for screen
design, the laziest option is to work with and adjust colors in the RGB color
space. There are two problems that arise while working in the RGB color space,
though. One of which is obvious, the second of which is not.
The Intuitive Mixing problem
The first problem I'll outline is what I call the Intuitive
Mixing problem. The inverse of this problem will become our second
requirement: that our tool must allow for mixing and adjusting colors
intuitively. This problem stems from the fact that, since screen design is
actually light design, light color definitions are based on an additive color
system.
Most of us have fond memories of painting when we were
young. Teachers used this opportunity to have us learn about the primary colors:
Red, Blue, and Yellow. With these three paint colors, you could mix them
together to form any other color, like Blue + Yellow = Green. Then you got
your hands messy, and actually got to create Green yourself... it was lots of
fun!
Paint is an example of a subtractive color mixing
system, because when white light hits a surface, some light is absorbed (or
subtracted) and some light is reflected back. White light is a combination of
all wavelengths of light, which is the same as saying it's the combination of
all colors or hues of light. For example, red paint absorbs all color wavelengths
of light except red, reflecting red light back. This is why if you mix
all your color paint together, you'll get a dark brown or black - that's
because it's absorbing most or all the different color wavelengths, and not
allowing much to reflect back.
Painting when we were young is the last positive experience
most of us had learning about color theory. A fair number of us also had to
endure a brief section of physics and light in high school; but, on the whole,
it probably wasn't as fun or inspiring as finger painting. This is actually
the crux of the Intuitive Mixing problem, though. Mixing different color
wavelengths of light together is actually an additive process. So
mixing all them together equals white (not black), and Red + Green = Yellow.
The knee-jerk reaction to Red + Green = Yellow is why, in my
opinion, the RGB color space fails the Intuitive Mixing requirement. Even for
designers who work with RGB all the time, there seems to be something not quite
right about it.
Here is an example of an RGB color that is mostly Red and
Green:
So, we'll add it to the list. So far our comparison matrix
looks like this:
|
RGB Format |
Intuitive Mixing |
RGB |
✔ |
✖ |
HSL to the rescue... kind of...
If you've ever fiddled with three RGB sliders, trying to get
to a certain color, you'll quickly realize that it's not an efficient way to
define a color. Shouldn't there be a way to take all the colors in the RGB
color space, and arrange them in a more intuitive way? There is, in fact; and
it's called HSL: Hue, Saturation, and Lightness.
HSL (and other systems, like HSV and HSB) eliminate the need
to individually specify each additive primary color, and instead, has you
specify three other metrics.
Hue is a more specific term to what might be referred
to as a "base color". You can have dark green, light green, forest green, etc...
but their base color is still just green.
Saturation is how pure that base color is.
Saturation can be thought of as a gradient between the base color, and a gray
color of equal lightness.
Lightness is probably the most intuitive aspect of
HSL - it's really just how light or dark the color is. You can imagine a base
color in the middle, with a gradient fading to white on one side, and fading to
black on the other side.
Here is an example of an HSL color with a Blue hue, fairly
saturated, and fairly dark:
As a side note, there are two cousins of HSL: HSV and HSB,
which stand for Value and Brightness. They are similar concepts to Lightness,
but not the same thing. For this discussion we'll be sticking to HSL.
Using HSL to define a color is conceptually much easier than
using pure RGB values - which means HSL passes our Intuitive Mixing
requirement. And even though we can't specify HSL values for screen design,
they are easily translated to RGB values (once we've got the color we want).
Actually, HSL and RGB share the same conceptual color space - another way of
saying this is that HSL is just all the RGB colors re-arranged in a more
logical way.
So, we've added another color space to our comparison
matrix:
|
RGB Format |
Intuitive Mixing |
RGB |
✔ |
✖ |
HSL |
✖ |
✔ |
If these were our only two requirements, working with HSL
and translating to RGB would meet our needs for screen design. But wait,
there is one more problem to overcome...
The Desaturation Problem
Designs usually require many colors, so designers are
usually not just interested in one color, but how a set of colors look and
interact in a single space. Hue is important because many base colors have
social meanings (RED = BAD, GREEN = GOOD). But besides this, how colors
contrast with each other is incredibly important. Does the color stand out and
grab your attention? Or does it stand out just enough to be read? Contrast is
a powerful tool in any design.
HSL lets us easily compare the lightness or darkness of any
two colors. If you reduce the saturation component of a HSL color, you are
left with a gray value, ranging from 0-100%. Finding this value for a set of
colors makes it easy to mathematically compare the lightness, or difference of
lightness (contrast) between all members of a set.
Let's say, for example, I want to work with a Blue and a
Yellow of equal lightness. They are different hues, sure, but I don't want one
to be darker or lighter than the other. So, I take a pure RGB Blue and Yellow,
and desaturate them to find their relative lightness value. For dramatic
effect, included below are the saturation steps 100%, 66%, 33%, and 0%.
The result of our desaturation process resulted in 50%
lightness for each color. Which gives us our answer: the blue and yellow color
above are just as light as each other.
This is where the problem comes in: those two colors are not
the same lightness. We asked the RGB color space to do some math for us to see
if one was lighter than the other, and the answer was "Equal lightness". But
if we ask our eyeballs to determine which is darker, it's very clear the blue
color is much darker than the yellow color. So what gives? It turns out the
RGB color space is the wrong shape.
The RGB cube
The RGB color space is very simple to describe. The three
additive primary colors can each be specified on a 256 point scale. All color
spaces are three dimensional - one of the effects of this is that you can't lay
out all the colors on a flat plane. The RGB color space happens to be a cube.
It can be visualized by graphing each of the RGB components in three
dimensions.
The corners of the RGB cube are the three additive primary
colors (Red, Green, and Blue), the three additive secondary colors (Magenta,
Yellow, and Cyan), plus Black and White. A single face of the RGB cube has a
primary, two secondary, and a non-hue corner. The entire outside of the cube
is comprised of fully saturated colors, and as we move toward the center of the
cube, the colors become less saturated (or closer to 50% gray).
The reason the RGB color space is laid out like this
is because it makes sense to computers. 256 happens to be a number that is
stored well in computer memory, with no space wasted, so we're able to specify
a large range of colors. Actually, there are 2563 distinct colors
in the RGB color space, which equals 16,777,216. Each pixel on your screen is
actually comprised of three sub-pixels: a Red, a Green, and a Blue. Each
sub-pixel can be at lightness = 0 (all the way off), lightness = 255 (all the
way on), or 254 steps in between. This is how more than 16 million screen
colors are generated.
The computer doesn't differentiate between these colors.
Incrementing the Red sub-pixel 10 levels is the same as incrementing the Green
sub-pixel 10 levels. Spatially, that means all colors in the RGB cube are
equidistant from each other. If we were to start at any color in the cube, and
travel three colors to the left, or three colors to the right, the distance is
the same. This may seem either confusing, or oversimplified, but it matters when
we start talking about the gamut, or curve, of a color space.
This means we have a new requirement: Accurate Lightness.
|
RGB Format |
Intuitive Mixing |
Accurate Lightness |
RGB |
✔ |
✖ |
✖ |
HSL |
✖ |
✔ |
✖ |
LAB to the rescue... kind of...
Remember the Yellow and Blue lightness problem outlined
above. We asked RGB which one was lighter, and the answer was that they were
the same lightness. That is because the Yellow corner and the Blue corner are
equidistant from the center of the RGB cube.
The point is this: the RGB color space makes sense to
computers, but it doesn't correspond to how the human eye perceives color.
Taking our color space model, this means the human eye doesn't use a cube to
sense how close or far away colors are from each other. For example, starting
at a color, traveling three colors to the left and three colors to the right,
you might be traveling different distances. So what is the shape of the color
space that our eyes can see?
The LAB color space
is a generic term that applies to many
different efforts to answer this question. This color space was the result of
decades of research that looked into how colors physically stimulated the eye.
There are many LAB variants, each emphasizing different things. For our
purposes, we're going to stick with CIE 1976 (L*, a*, b*) variant of the LAB
color space, which is one of the more common ones.
So what is the shape of the LAB color space? Well, the
specific answer is hard to describe. One of the limiting factors is that the
human eye can see more colors than can be displayed through RGB... so if you're
reading this on a computer, it's impossible to show a picture of the full LAB
color space. But, for now, the important answer to the shape question is that
it's curvy, and definitely not a cube. Darkness and Lightness are different,
depending on what hue you are dealing with.
Many thanks to Jacob Rus and Wikipedia for this image.
Here is a look at three different slices of the LAB color
space at 75%, 50%, and 25% lightness. Remember, the hard edges of these color
shapes are not actually hard... but the point is that the color space our eyes
see is kind of curvy, in all three dimensions.
The L in LAB stands for Lightness. With a little math, we
can take a RGB color, and find out a more accurate lightness that isn't based
on the RGB cube. For example, now we could graph the relative LAB lightness
values of the RGB Spectrum. By RGB Spectrum I mean the Hue selection component
in our HSL color chooser... or, RGB colors where saturation = 100% and lightness
= 50%.
Looking at the graph it makes sense. There are some
lightness peaks, around Yellow, Cyan, and Magenta, and there are some lightness
valleys - mostly around blue, but around red, and green as well. We can use
this new information to lay out colors in a way that accurately reflects that
color's true lightness. LAB allows us access to accurate lightness... that is
great news!
The bad news is that the other two dimensions of LAB are
based on additive color mixing. The A dimension is colors between green and
magenta, and the B dimension is colors between blue and yellow. This is a
logical way organize a color space that applies to light. But, unfortunately,
this means LAB fails our Intuitive Mixing requirement for the same reasons RGB
fails.
But, we can add LAB to our comparison matrix to see how
everything compares:
|
RGB Format |
Intuitive Mixing |
Accurate Lightness |
RGB |
✔ |
✖ |
✖ |
HSL |
✖ |
✔ |
✖ |
LAB |
✖ |
✖ |
✔ |
Funny, I see a PASS in ever column...
The Solution: a new color space
Well, maybe not a new color space in the technical sense.
But at least a tool that would satisfy all three requirements:
|
RGB Format |
Intuitive Mixing |
Accurate Lightness |
RGB |
✔ |
✖ |
✖ |
HSL |
✖ |
✔ |
✖ |
LAB |
✖ |
✖ |
✔ |
hsLab |
✔ |
✔ |
✔ |
Formulas for converting between RGB, HSL, and LAB are widely
available. So, essentially, this new tool will be a few points of color design
philosophy, mixed with some color conversion math behind the scenes.
Some design criteria
Scope the tool to RGB color space
One of the first sections of this article was titled
"Starting, and ending, with RGB". It might be tempting to base our new tool in
the LAB color space: it can describe so many colors... including ones that fall outside
of the RGB space, and even colors that can't be seen by humans. LAB was made
to be comprehensive, and it is. But do we really need all that?
Since the goal of this tool is to help with screen design,
we're actually going to take the confines of the RGB color space as a welcome
restriction. The end goal is to determine a RGB color, so our starting set of
possible colors should also be RGB.
16 million colors is too many
As we learned previously, the RGB color space can specify
more than 16 million colors. The fact is, if you take two RGB colors that are
one step different, and put them next to each other, it's impossible to tell
them apart. Since RGB steps are 0-255, we can look at the factors of 255 to
find step numbers that can traverse the RGB space without remainders. That is
to say, if we start at zero, and step over a certain number of colors each
time, we can land on 255 at the end.
Actually, walking through the RGB color space with the 51
step size will get you the old "Web Safe" color palette. But what the picture
illustrates above is taking single steps will only result in imperceptible
differences. Therefore, it will be a useful feature of our tool to chunk the
entire RGB color space with larger step sizes.
Generating a color chooser
This is an overview of how our new tool will be laid out,
and how colors in the chooser will be determined.
RGB Format for screen design
Since we're starting with the RGB color space, we can use a
step to select an evenly distributed subset of the RGB color space. This will
become our working set, and we can arrange these colors as we see fit.
Intuitive Mixing
This requirement will inform how our color chooser tool is
laid out; or, how we're going to map our three dimensional color space onto a
two dimensional tool. The one color space that met this requirement is HSL, so
we'll borrow its format. The first choice, or control, will be the hue
selector. Once a hue "base color" is selected (the first dimension) we'll lay
out the other two dimensions in a square. The vertical axis of the square will
be Lightness, and the horizontal axis will be Saturation.
Accurate Lightness
Even though our tool is laid out like a HSL tool, we will
use LAB to compute the lightness component. The HSL definition of saturation
and hue does not pose any problems, so we'll stick with those.
Bringing it all together
Here is a walkthrough of our process
- Choose a RGB step [5,15,17,51]
- Choose a HSL Hue that will be our base color
- Using the base color and the step size, create a subset of RGB colors that
correspond to the two dimensional HSL saturation and lightness space
- For each color in this subset of colors, determine the LAB lightness
- Re-organize the two dimensional space with HSL saturation and LAB lightness
To use our Blue vs. Yellow example above, here's how the two
colors are re-mapped with our new hsLab tool, with a RGB step of 5. The
lightness value of the blue base color is 32%, while yellow's is 95% - a much
better representation of their relative lightness.
Because these images use an aspect of LAB, they also show
the curvy shape of the LAB color space.
A few final thoughts
The primary value of this tool is the accurate lightness
comparison. In the tool, horizontal rows of colors have equal lightness.
Laying out colors based on inherent properties should positively influence
color choices.
The hsLab tool also begins to show interesting saturation
patters. Columns of color have equal saturation - but when combined with the
lightness dimension, they form these interesting "tree ring" like patterns.
Most other color pickers artificially stretch these colors into a square. The
hsLab tool lets the colors fall where they may, which better highlights their
relationship to other colors in both the saturation and lightness dimension.
This is just one way to organize a set of colors... it
emphasizes certain aspects and is scoped certain ways to meet specific needs.
Is it the end-all-be-all color choosing tool? Well, probably not. But I like it,
and if you don't like it, I encourage you to make your own.