HTML & CSS From Scratch, Volume 4: CSS Color Units and Color Properties!
This is the 4th post in a series on HTML and CSS. To start from the beginning, see my first post, which provides an introduction to the philosophy behind HTML & CSS and dives into the details of some basic HTML elements and display properties.
In my last post, I covered some basic styling concepts, units of measure and font and text properties. We’ll continue from there today to cover everything you will need to know about how color works in CSS, as well as the color properties that you can assign. We’ll also discuss a bit about how color has developed from the original CSS specification to CSS3 (and get a glimpse of what might be coming in CSS4).
Color in CSS
Like me, you might have learned as a child in elementary school that the primary colors are red, blue, and yellow. And that’s true(ish) — for subtractive color like paint and printing ink. We call paint subtractive color because it subtracts wavelengths from light — the more pigment you add to a white base, the more light gets absorbed by the mixed paint, and the fewer wavelengths you see. For example, if you want to make a pink paint darker, you might add red. For additive color — light — the more color you add, the brighter the color gets. With light, the primary colors are red, green, and blue. These are often referred to with the acronym RGB. Add them together in different quantities, and you can make every color that appears on your computer screen, including white (which is made from all three together, at full strength). Going back to the early days of the web, each of these colors (red, green, and blue) was represented by an 8-bit number (a value from 0–255). Modern computer screens can display an even wider range than this, but 8-bit numbers are sufficient for web color applications, and they are the standard.
Just as there are multiple units of measurement for distance in CSS, there are also multiple units of measurement for color. We’ll go into more depth below, but following are the options:
- Named colors: recognized color names that map to a specific RGB value
- RGB(A): a representation of the color’s Red, Green, and Blue (RGB) components. Also, there is a more recent standard (but well-supported) that also includes an Alpha (RGBA) value at the end.
- Hexadecimal: a shortcut for writing RGB values. Widely supported and used across the web, since its early days.
- HSL: an alternate means for displaying color as Hue, Saturation, and Lightness. This is a more recent standard that was added with the CSS3 specification, but it is widely supported (IE9+).
- HWB: a similar standard to HSL that represents colors as Hue, Whiteness and Blackness. A suggested standard for CSS4. Not yet supported.
- CMYK: a standard based on printing processes that stands for Cyan, Magenta, Yellow, and Key Black — ink colors used for printing (think of the blue, red, and yellow primary colors you learned in elementary school, and substitute magenta for red). This is another suggested standard for CSS4. It is not yet supported, but once it is, it could be particularly useful for defining print styles. Ask any graphic designer who has designed branding across print and web, and s/he will tell you that converting RGB to CMYK is not always simple. If you print a file in RGB color, the output may be quite different from what you intended — often a bit more faded and less bold than it felt on the screen. As such, adding CMYK color model will be a welcome addition for visual designers hoping to create a professional, cohesive brand across all media.
RGB Color Values
This is probably the most straightforward of the web color models. Each component color (red, green, and blue) is represented by a number between 0 and 255. For example, if you want to make the background of a webpage a bold red color, the style might be:
background-color: rgb(255, 0, 0);
If I want to make a pink color, though, I need to mix in the blue and green to make it brighter. For example:
background-color: rgb(255, 180, 180);
Remember from above that I told you that red + green + blue make white? Well, if you add green and blue in equal amounts, like I did above, you keep the color balanced on red, but you brighten it until it becomes pink. Likewise, if I want a dark red, I would reduce values, for example:
background-color: rgb(100, 0, 0);
If I want a less saturated, dark red, I simple reduce the amount of red while increasing the amount of blue and green:
background-color: rgb(80, 20, 20);
That said, people typically don’t find pure red, blue, or green to be pleasant to look at. Pure red, pure green, and pure blue look unnatural to the human eye. You’ll find that most colors on sophisticated websites — even reds, blues, and greens, will lean slightly toward another color. For example, Koto’s brand color is “red,” but it has a bit more green than blue, making it lean a toward orange:
rgb(240, 78, 45).
Hexadecimal, a.k.a. “Hex codes” (an RGB shorthand)
This is a method of representing color in which the RGB values are preceded by a
# and each number is represented by a 2-digit, base-16 value (with the letters a–f used to represent the values 10–15). This method was created because it’s a handy shorthand for an 8-bit number, since it can represent color values in only 2 digits. Some simple base-16 conversions to give you a feel for the range that each color (red, green and blue) may receive:
10= 16+0 = 16
19= 16+9 = 25
1f= 16+15 = 31
50= 16*5+0 = 80
7f= 16*7+15 = 127
99= 16*9+9 = 153
aa= 16*10+10 = 170
bb= 16*11+11 = 187
cc= 16*12+12 = 204
dd= 16*13+13 = 221
ee= 16*14+14 = 238
ff= 16*15+15 = 255
The zero end of the range means that the color is not present, and the 255 end of the range means that it is in full force. So a hex code of #000000 is black (no color) and a hex code of #ffffff is white. Note that capitalization doesn’t matter in hex codes. #FFFFFF works just fine, too. The important thing is to be consistent. W3C Schools website claims that uppercase letters are easier to read. Having studied literacy as part of my UX work at Learn with Homer, I disagree, and I use lowercase letters because both literacy research and personal experience has found lowercase letters easier to read quickly, at a glance, presumably due to the wider variation in heights and shapes.
One more thing about hex codes: simple ones in which the two digits of each color component are the same, such as #ffffff or #000000 or even #112233 can receive a short(er)hand code of #fff, #000, or #123.
HSL is another way of thinking about RGB color. HSL stands for Hue, Saturation, and Lightness. These are common terms in the art and design world, but not nearly as common in the world of software engineering, so let’s break that down:
- Hue: If you mapped out the range of perceptible colors along a line, where would each RGB color lie along that line? Now suppose you took that line and wrapped it around into a circle: then you could position red at one point, green at another and blue at yet another point, and then assign an angle any mix of red, green and blue. The HSL model does just that: it maps colors to a color wheel, and each hue has a particular angle associated with it. Red is at 0°, Green is at 120°, and Blue is at 240°. As you rotate a third of the way around circle, you move through all of the colors between red and green until you get pure green at 120°. Keep going, and you move through all of the colors between green and blue, until you hit pure blue at 240°. Keep going still, and you move through the colors between blue and red, until you get all of the way around the circle, to 360° — which is the same point as 0°.
- Saturation: Hue just tells you the core color, but it doesn’t tell you how deep the color is. Saturation does that. If you completely desaturated colors on a webpage, it would be in grayscale. Saturation is represented in the HSL model as a percent from 0% (no color) to 100% (full color).
- Lightness: How light or dark a color is. Remember above where we added some green and blue to make the red lighter? In the HSL model, we explicitly control lightness through the lightness variable, rather than by adjusting the component colors individually. Like saturation, lightness is represented as a percent value from 0% (black) to 100% (brightest color). Also, an aside: designers and design programs often call this “Brightness,” so you may also see this color model abbreviated as HSB. If you do, know that the only difference is in the naming; HSB and HSL are otherwise identical.
Let’s see HSL in action, using the color
#ff0080, which, coincidentally, was my favorite color as a child (and I’m still quite fond of it, today). Some color systems call this
fuchsia, but if you use the
fuchsia color name in CSS, you’ll get
#ff00ff, which I don’t find as pleasing—the latter is seen as a bit more purple and the former is more of a hot pink.
Looking at this image, we see HSB (remember — it’s the same as HSL), RGB, and hex values for this color, as well as CMYK. The way the standard color picker works is that it isolates a single hue (the ‘H’ in HSB/HSL) and allows you to pick different shades of it.
If I move along the vertical axis, I change the lightness (or brightness), and if I move along the horizontal axis, I change the saturation. You can see this most clearly by looking at the edges: at the top of the square, we go from bold color to white, because a fully desaturated, fully bright color is white!. At the right, we go from bold color to black, because a fully dark color is black! The entire bottom edge is black, because any color, no matter how saturated it is, turns black at zero brightness. Lastly, the left edge is completely desaturated, so we move from black at the bottom to white at the top. Any hue at zero saturation will turn to grayscale. We can confirm this by picking some colors from the middle of each side.
Note that your browser can show you a very similar color picker! I focused on Adobe Illustrator’s color picker, however, so that you could see how HSB/HSL compares to RGB and hex codes. Your browser, however, likely only shows you one color model at any given point, based on what you wrote in your CSS.
HSL color is supported from IE9 forward, so it is safe to use on most websites.
CMYK and HWB Color Models (and more)
I won’t go into detail about these color models, since they are not yet supported, but if you are curious, here are a couple of threads to pull on:
- HWB color explanation in the current working draft of the CSS4 specification
- CMYK color in the same page — the current working draft of the CSS4 specification
- If you scroll around in the specification, you’ll see that there’s even more in it — Lab, LCH, gray, and sRGB. I won’t go into detail those in this post, either, but they’re in the works!
Lastly, as I alluded to, above, there are many colors that you can use via named shortcuts. For example, if I write the style,
background-color: red;, the browser will interpret it as
#f00. The only color names I use with any frequency are
white. However, there are over 140 named colors to choose from! If you want to see your options, check out the full list of HTML color names at W3C Schools. (If you scroll about in the upcoming CSS color specification, you’ll see the addition of
rebeccapurple for CSS4.)
Transparency in RGB, HSL, and Hex Color
Transparency in rgb and hsl colors is simple: you just add an alpha value between 0 and 1:
background-color: rgba(255, 0, 0, 0.5); /* red at 50% opacity */
color: hsla(0, 100%, 0%, 0.87); /* This is red in the hue scale, but it's actually black, since it has 0% lightness: black at 87% opacity. */
Note above that I added an ‘a’ to the end of
hsl. Whenever you include an alpha value, you must note that it is
There’s also a hex notation in which the alpha value is represented by a hex number at the end of the code (making the code 4 or 8 characters long, e.g. #fff8 or #ffffff88), but it is not supported by Microsoft IE or Edge, as well as several mobile platforms, so I do not recommend using it. If you want to read up on how it is used, though, I recommend this article from CSS Tricks that explains hex codes with transparency.
Color (and Background) Properties
Color can be assigned in several places, some of which we have seen already:
color: the color of text on the page. In the old days of HTML, this was simply named “color” because of the implication that text is always in the foreground. The initial value for a browser is
background-image: the url for an image to display in the background of a container. This can be used in conjunction with background-color, e.g. if your image has transparency. Format is
background-image: url(relative-or-absolute-path-to-image-here);. The URL you specify can be on any domain. It doesn’t need to be hosted by your site (though it can be). The initial value is
background-position: Position can be determined using keywords or a distance measurement, with the x (horizontal) position followed by the y (vertical) position. If using distance, both relative or absolute units are allowed. Keywords are
center. This might be expressed as
background-position: left bottom;or
background-position: 10px 20%;. Note that if I just use a single keyword
center, the browser will assume center for both horizontal and vertical positioning. There’s one tricky (and kind of awesome) detail about percentages for position: they are calculated width/height of the container minus the width/height of the image, such that a position of 100% 100% places the image in the bottom right corner of the container.
background-size: size to use for the background image. See below for a bit more detail on this.
background-repeat: how a background image should (or shouldn’t) repeat in the container. The default value is
repeat, which means it will repeat in both x and y directions (horizontally and vertically) if the image is smaller than the container. Alternative options are:
repeat-y. CSS3 added
spaceas options, too, and they’re well supported (IE10 and up. Theoretically IE9, but it has issues). Both of these will avoid clipping the background if it doesn’t repeat a perfect number of times.
roundwill adjust the image positioning to crop opposite edges evenly, while
spacewill space out the repeated image to make it fit evenly.
background-attachment: whether or not the background scrolls with the content. The initial value is
scroll. Also an option:
background-origin: what box-sizing model to use for resizing the background. Default is
padding-box, but other options include
background-clip: Similar to
background-origin, this defines what box-sizing model to use for clipping the background: where does it get cut off? Default is
padding-box, but other options include
background-color: the background color of a container. The initial value is
background: a shorthand for all of the background properties, preferably in the order listed above—but browsers are forgiving and the spec has changed over time. For example, the spec used to call for the color and then the . See below for an example:
A quick examination of
The default is
background-size: auto, which will size the image at its inherent dimensions. Other options are:
- length: width and height dimensions in relative or absolute units. If only width or height is defined, the other will default to
cover: Scale the image to cover the entirety of the element. This means your image may be cropped vertically or horizontally, depending on how its aspect ratio compares to the container’s.
contain: Similar to cover, but scales the image to always fit inside the element. This may result in some extra horizontal or vertical space around the image, depending on how its aspect ratio compares to the container’s.
Example of Background Properties & Shorthand:
background-position: -10px -10px;
background-size: 200px 150px;
That’s a lot of properties to declare! If you want to, you can capture them all at once:
background: url(http://newtownsquarevet.com/wp-content/uploads/2017/01/kitten-pounce.png) -10px -10px / 200px 150px repeat-y fixed border-box border-box #ff0080;
FYI: I grabbed the image in this code from a google image search; if you’re in the Philadephia area, give Newtown Square Veterinary Hospital some business as a thanks for creating and hosting such a great kitten GIF.
Or if you like clearer separation between properties to show intent, you can do that, since CSS is like HTML—lots of white space collapses to a single space:
-10px -10px / 200px 150px
Backgrounds in action
An Aside on How HTML and CSS Have Developed
One thing you’ll find as you’re learning CSS is that there are a lot of quirks from when HTML and CSS were first developed, which we now maintain, going forward. This is because if we change the specification completely, old websites could break. As such, each HTML and CSS specification builds on the last. If you wrote something today using purely HTML and CSS approaches from the early days of the web, it should still render correctly in modern browsers. This is why, for example, browsers support different orderings for the
Yes, you can have multiple backgrounds! Same rules apply, but separate their properties with commas.
Open up that codepen above, add a second layer of background images. Add some (semantic) elements with text. Play with color, background-color and image position and size.