CSS color and background-color
Two properties handle color on most elements. color sets the text color. background-color fills the content area and the padding, and by default it also runs under the border, which you would notice with a dashed border. In this lesson the buttons get white text on blue, and the second link gets the reverse.
The code
Add two lines to .btn, then a new rule below it for the light variant:
.btn {
/* Lesson 2: margin */
margin: 0 0.5rem 0.5rem 0;
/* Lesson 3: padding */
padding: 0.75em 1.5em;
/* Lesson 4: border */
border: 2px solid #1d4ed8;
border-radius: 0.5rem;
/* Lesson 5: color */
color: #ffffff;
background-color: #1d4ed8;
}
/* Lesson 5: the second color scheme */
.btn-light {
color: #1d4ed8;
background-color: #ffffff;
}
As a reminder, this is the markup from lesson 1. Only the middle element carries both classes:
<a class="btn" href="#">Read the guide</a>
<a class="btn btn-light" href="#">Parts list</a>
<button class="btn" type="button">Copy code</button>
The position of .btn-light in the stylesheet matters. Both selectors are a single class, so they are equally specific, and when two equally specific rules set the same property, the later one wins. The second link matches both rules: it takes margin, padding and border from .btn, then gets its two colors replaced by .btn-light.
Reload. The first link and the button are now solid blue with white text. The second link is white with blue text inside a blue border. The links have also lost the browser's default link blue and visited purple, because a rule you write for an element beats the browser's built-in styles for it.
Three ways to write the same blue
| Notation | Value | How to read it |
|---|---|---|
| Hex | #1d4ed8 |
Red 1d, green 4e, blue d8, each from 00 to ff |
| rgb() | rgb(29 78 216) |
Red 29, green 78, blue 216, each from 0 to 255 |
| hsl() | hsl(224.3 76.3% 48%) |
Hue 224.3 degrees, saturation 76.3%, lightness 48% |
Hex uses two hexadecimal digits per channel, and the letters a to f stand for 10 to 15. So 1d is 1 × 16 + 13 = 29, 4e is 4 × 16 + 14 = 78, and d8 is 13 × 16 + 8 = 216. That is the rgb() row written in base 16. A three-digit hex value doubles each digit, which makes #fff the same as #ffffff, pure white.
The rgb() and hsl() forms above use the current syntax with spaces. You will also see the older comma form, rgb(29, 78, 216), which still works everywhere. Both forms take an optional alpha value for transparency after a slash: rgb(29 78 216 / 50%) is the same blue at half opacity.
Notice the decimals in the hsl() row. Conversions between notations round, and the tidier hsl(224 76% 48%) comes out as #1d4fd7, one step off in green and blue. Nobody can see that difference, but it explains why a color copied between tools sometimes changes its last digit.
Why hsl() is handy for shades
In hsl() the hue is a position on the color wheel (0 is red, 120 green, 240 blue), saturation is how strong the color is, and lightness runs from 0% for black to 100% for white. To plan a darker shade for a hover state, keep the hue and lower the lightness. The hover color in lesson 8, #1e40af, is about hsl(226 71% 40%): nearly the same hue, eight points darker.
We use hex in the project because it is short and every design tool copies it. Pick one notation per project and stay with it; mixing notations makes colors hard to compare by eye.
Readable text: contrast
Color for text is not only a matter of taste. The Web Content Accessibility Guidelines (WCAG) ask for a contrast ratio of at least 4.5:1 between normal-size text and its background. The scale runs from 1:1, the same color on itself, to 21:1, black on white.
| Text on background | Contrast ratio | Normal text (4.5:1) |
|---|---|---|
#ffffff on #1d4ed8 |
about 6.7:1 | Passes |
#1d4ed8 on #ffffff |
about 6.7:1 | Passes |
#ffffff on #60a5fa |
about 2.5:1 | Fails |
The light variant is the same pair of colors swapped, so its ratio is identical. The paler blue in the last row looks friendly and is hard to read. Browser developer tools show the ratio when you inspect a color, and it takes seconds to check before you commit to a palette.
Questions
Why does changing color not change the border?
It would if the border had no color of its own. A border without a color uses currentColor, the element's text color. Lesson 4 gave the border an explicit #1d4ed8, so changing color leaves it alone.
Can I use color names?
Yes. CSS knows names such as white, navy and rebeccapurple, and lesson 1 used red for its test. Names are fine for quick experiments, but the list is fixed and most real palettes are not on it.
Should I write background or background-color?
background is a shorthand that also sets images, position and repeat. background: #1d4ed8 works, but it quietly resets the other background properties too. background-color changes the color and nothing else, which is easier to reason about later.
Try it: in the online HTML editor, swap the blue for hsl(224 76% 30%) and then hsl(224 76% 65%), check each against white text in the developer tools, and keep whichever passes 4.5:1.