What the #FFFFFF? Hexadecimal Math and Color Theory in Web Design

Reading Time: 7 minutes

Today’s HTML recognizes 140 standard colors by name, but what happens when you want something a little more red than DodgerBlue, or some shade in between Bisque and BlanchedAlmond? If you want to graduate from the little crayon box to the big one with all the colors, you have to learn a little math. 

Graphic designers, especially those who design for the web, often find themselves having to be experts in a base-16 number system, instead of our normal, human-speak decimal system, often without even knowing it. Those who’ve seen #FFFFFF in HTML or CSS code, or perhaps while adjusting color in photo editing software, may understand it represents white, but they may not understand how to convert this mysterious representation into color theory.

Color theory is just that: the theory of how to make colors. This includes any variations caused by creating color with pigment (printing, painting, etc.) versus creating color with light directly (television, projection, prisms). In color theory, all colors on the visible spectrum can be created via the right combination of primary colors. In pigment-based systems, these colors are Cyan, Magenta, Yellow and blacK (CMYK.) In light-based systems, these colors are Red, Green, and Blue (RGB.) This article focuses on color theory for monitors and displays, so we’ll stick with RGB for now.

If all lights are on, the yield will be pure white. If all lights are off, the yield is pure black. We can indicate fully on with FF, and off with 00. This means that #FFFFFF is all white, as in all lights are at maximum setting: Red: FF, Green: FF, Blue: FF (in that order). #000000 is all black, so Red: 00, Green: 00, Blue: 00.

*** Note also the # sign. Usually we denote hexadecimal with “0x” or “#” to make it distinct from decimal numerals or letters.

By knowing that FF is a maximum possible value, and 0 is a null value, one can easily determine a pure Red (#FF0000), Green (#00FF00), or Blue (#0000FF). But what about any of the colors in between? That requires either a reference chart, a little more math, or some experimentation.

If reading the words “a little math” caused you to hyperventilate a little, you’re not alone. Before learning more about hexadecimal, let’s think about what we already know: decimal.

If we were inventing a way to tell a machine how to mix different colors consistently we might use some kind of unit system: “Combine 3 Reds with 5 Greens and 1 Blue!” After a while, however, we’d realize we need a LOT more of each color unit, or else the number of colors we can produce are quite limited.

Another problem is that humans prefer decimal, what with our biological default setting of ten fingers and ten toes. Computers, with their on/off toggle switches, prefer binary, which doesn’t render evenly into tens. This means our system needs two things: more colors, and a way for computers to count them.

When we count (I’m assuming you’re a human here, apologies to any AI or bots), we follow a base-10 system. That means that each column in our mathematical system is a base of 10. Those who panicked at “a little math” and whose eyes glazed over at numbers might need a bit of help recalling bases and exponents.

In “2^3” or “two to the third power,” the 2 represents the base, or number being multiplied. (There is another way to write this, with the 3 in superscript, but this way, with the caret, will render across all text encoding without fancy styles or formatting.) The 3 represents the exponent, or number of times the base is being multiplied by itself, or 2 x 2 x 2= 8. Similarly, “10^3” is 10 x 10 x 10, or 1000, while 10^2 is 10 x 10, or 100.

There are special rules with bases and exponents that many may recall memorizing in school. The first is that anything to the power of zero is always one. 2^0, 10^0, 16^0, doesn’t matter. A base times “not nothing but also not itself” is one. Another special rule is that any base to the power of one is itself. This makes perfect sense, as 2^1 is the same as 2 by itself not being multiplied by another 2.

To review, for the math impaired, we now have assembled the following knowledge:

10^0= 1, 10^1= 10, 10^2=100, 10^3=1000

2^0=1, 2^1=2, 2^2=4, 2^3= 8

If you think back to your earliest counting lessons, you may recall learning “places,” i.e., the ones place, the tens place, the hundreds place, the thousands place. Note the similarity to our base-10 references above. It means the same thing, we just have them in the wrong order. Let’s fix that:

10^3 | 10^2 | 10^1 | 10^0

thousands place | hundreds place | tens place | ones place

For the heck of it, let’s try doing the same thing with our base-2 references…

2^3 | 2^2 | 2^1 | 2^0

eights place | fours place | twos place | ones place

This means that if we put a one in any of these columns, it counts as that number. Just as a one in the hundreds place followed by two zeros makes 100, a one in the fours place followed by two zeros makes 4 (four + 0 + 0). This means (take a deep breath, math phobes) that in binary, 100 = 4.

Your eyes may already be glazing over, trying to figure out what exponents have to do with trying to find the perfect shade of beige. Fear not, reader. It just takes a little logic and a little substitution.

Imagine, if you will, that you want more colors than binary or decimal will allow you to count. Imagine you want more than 10 Red + 8 Green + 9 Blue, or 1 Red + 2 Green + 1 Blue. Imagine you wanted access to millions of color variations. This means not only that you’ll need bigger numbers for your color units, but also that this number system must be stored, read, and comprehended by a computer. Enter hexadecimal. Hexadecimal, as its name implies, isn’t that far from decimal. “Hexa” here represents 6 plus decimals 10, so this means base-16 math.

Let’s insert this into the system we already know, keeping it shorter so the math doesn’t get out of hand:

16^2 | 16^1 | 16^0

256-place | sixteens-place | ones place

This would mean that a one in every column equals (256+16+1), or 0x111=273. The binary for that, if you’re playing at home, is 100010001. You can see why using hexadecimal instead of trying to represent these numbers in binary would save space. (You can also see why using 0x or # to clarify when you’re working with hexadecimal instead of decimal or binary might be helpful.)

We understand that something placed in a column means you have that many of that column. We get that 100 in a base-2 system is 4 + (no 2s) + (no 1s) = 4. We get that 523 in decimal is 5 hundreds + 2 tens + 3 ones, or 523. There is a problem with hexadecimal however: we don’t have enough digits to go around. Think we do? Try counting, using only two hexadecimal places: 01, 02, 03, 04, 05, 06, 07, 08, 09, 0?, 0?, 0?, 0?, 0?, 0?, 10. That last 10 is one 16 + zero ones. Therefore we need some sort of single digit solution that can act as a placeholder until we get to 16 and can switch to the sixteens-place. The bad news: we are all out of numerals. The good news: Hey, has anyone raided this bag of letters yet?

Of course, letters are used in mathematical equations all the time as variables. For this reason, when using letters as digits in hex (as hexadecimal is often abbreviated), they are often capitalized unless the hex number is clearly marked in some other way. Let’s try counting again using this new trick:  01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10.

This gives A a value of 10, B a value of 11, and so forth. 0F being the last option before rolling over into the next place of 16, is therefore 15.

Let’s expand this concept further. 0x3B would then equate to 3 sixteens and 11 ones (In decimal: 3 x 16= 48 + 11 = 59). Therefore 0x3B would be 59 in decimal. 0xAF would be 10 sixteens and 15 ones, 160+15= 175. 0xFF is 255, the maximum you can have before rolling over into the next column, 16^3 or the 256ths place.

*** Note that although the maximum you can count to is 255, there are a total of 256 possible values when you include all zeroes as an option.

If we add our math and our art back together we may reasonably conclude something: the #FFFFFF system means we can have 256 values of Red, 256 values of Green, and 256 values of Blue in any combination (remembering that we count not having any as a possible value.) This yields millions of color combinations.

How might a designer use this new-found knowledge to their advantage? Imagine the web artist as a painter with a palette mixing colors. Bob Ross always knew when to use a little more red or a little more blue, or when to darken or lighten a color, and would mix the dab of blue or black into a color on his palette. The web designer does the same, only using math and light instead of pigments. If you want a little more blue, increase the blue number, now that you know how to read it. If you want the color a little lighter overall, increase all the RGB values evenly to get it closer to white, or #FFFFFF.

To use our example from the beginning of the article, what would you do if you needed something in between BlanchedAlmond #FFEBCD and Bisque #FFE4C4? Firstly, despite my earlier comments, both are much warmer than Beige #F5F5DC. You can see this from the numeric values: Beige is lower in Red, significantly higher in Green, somewhat higher in Blue.

Secondly, you can see that BlanchedAlmond and Bisque are quite close, numerically speaking. All of the Reds are in play for both colors. Bisque has fewer Green units in it, (228 compared to 235) but both are very high because the colors are light (thus closer to white or FF). Both are also quite high in Blue in order to achieve a light shade, but again BlanchedAlmond is a little higher at 205 compared to Bisque’s 196. If you liked one of these colors but wanted to make it a bit darker, you might subtract 5 or 10 from each RGB value column. If you wanted to make one of them cooler, you would increase the Green and Blue values.

While the average graphic designer working with web pages and online graphics may be able to get far with the standard 140 default colors, with a little bit of know-how can open up a whole new world. In the online world, the difference between the small crayon box and an immense one filled with a million options is as simple as 0x01, 0x02, 0x03.


Also published on Medium.