Lesson 25 of 32
Colors and Backgrounds
The color formats CSS understands — keyword, hex, rgb() and hsl() — background-image with linear-gradient, controlling size/position/repeat, and the currentColor keyword.
You've been using a handful of color keywords already without thinking about
it much — navy, red, white. CSS actually gives you several distinct ways
to describe a color, and picking the right one changes how easy your
stylesheet is to reason about and adjust later.
Four ways to write a color
.keyword { color: rebeccapurple; }
.hex { color: #3b82f6; }
.rgb { color: rgb(59, 130, 246); }
.rgb-alpha { color: rgba(59, 130, 246, 0.5); }
.hsl { color: hsl(217, 91%, 60%); }
.hsl-alpha { color: hsla(217, 91%, 60%, 0.5); }- Keyword — a named color like
red,navy,rebeccapurple. Readable, but there are only a fixed set of names and no way to fine-tune one. - Hex —
#rrggbb, three pairs of hexadecimal digits for red, green and blue. Extremely common, especially when copying a color from a design tool, but the digits themselves don't tell you much at a glance —#3b82f6gives you no intuition for what it looks like until you've seen it rendered. rgb()— the same red/green/blue values written as plain numbers 0–255 (or percentages).rgba()adds a fourth value, alpha, from 0 (fully transparent) to 1 (fully opaque).hsl()— hue (0–360, a position on the color wheel), saturation (0–100%, how vivid), lightness (0–100%, how close to black or white).hsla()adds the same alpha channel.
Modern CSS also lets you write rgb(59 130 246 / 0.5) and
hsl(217 91% 60% / 0.5) — space-separated with a slash before alpha — but the
comma syntax above works everywhere and is still extremely common; either is
fine to reach for.
Why HSL is often easier to reason about
Hex and RGB describe a color as a mix of red, green and blue light — accurate, but not how humans naturally think about color. "Make this a bit darker" or "give me five shades of the same blue" is genuinely hard to do by adjusting hex digits, because darkening a color changes all three RGB components in a way that isn't obvious from the numbers.
HSL separates which color (hue) from how intense (saturation) and how light or dark (lightness). That means you can hold hue and saturation constant and vary only lightness to get a consistent family of shades of the same color:
:root {
--brand-hue: 217;
--brand-sat: 91%;
}
.brand-light { color: hsl(var(--brand-hue) var(--brand-sat) 85%); }
.brand-base { color: hsl(var(--brand-hue) var(--brand-sat) 60%); }
.brand-dark { color: hsl(var(--brand-hue) var(--brand-sat) 35%); }Same hue, same saturation, three lightness values — three clearly related shades, and the relationship between them is visible directly in the numbers rather than hidden inside three separately-tweaked hex codes. This is a real, practical reason designers and developers often reach for HSL when building a palette by hand, even though hex remains extremely common for one-off colors picked from a design file.
background-color
The simplest background: a flat fill behind an element's content.
.card {
background-color: #f8fafc;
}Any of the color formats above work here.
background-image with linear-gradient()
background-image isn't limited to photos — CSS can generate a gradient
directly, no image file needed:
.banner {
background-image: linear-gradient(90deg, #3b82f6, #8b5cf6);
}The first argument is the direction — 90deg points left to right (CSS
gradient angles start pointing up at 0deg and rotate clockwise, so 90deg
is "to the right"). You can also use keywords instead of degrees:
.banner-alt {
background-image: linear-gradient(to right, #3b82f6, #8b5cf6);
}After the direction come color stops — the colors the gradient passes through, evenly spaced by default. You can add more than two, and you can pin any stop to a specific position with a percentage:
.sunset {
background-image: linear-gradient(
to bottom,
#fbbf24 0%,
#f97316 50%,
#7c3aed 100%
);
}Controlling size, position and repeat
Three properties shape how a background image (gradient or photo) fills its element:
.hero {
background-image: url("photo.jpg");
background-size: cover; /* fill the box completely, cropping if needed */
background-position: center; /* keep the middle of the image visible */
background-repeat: no-repeat; /* don't tile it */
}background-size—coverscales the image to fill the element entirely (cropping overflow),containscales it to fit entirely inside without cropping, and you can also give explicit lengths or percentages.background-position— where the image is anchored within the element, using keywords (center,top right) or lengths.background-repeat— by default, a background image smaller than its element tiles to fill the remaining space.no-repeatstops that;repeat-xandrepeat-ytile in only one direction, which is useful for a background pattern or a thin repeating texture strip.
currentColor: matching whatever text color already applies
currentColor is a keyword, usable anywhere a color value is expected, that
always resolves to the element's own computed color value. It's genuinely
useful anywhere you want something to match the surrounding text color
without duplicating that color value a second time:
.link-with-icon {
color: #1d4ed8;
border-bottom: 1px solid currentColor; /* always matches the text color above */
}
.link-with-icon svg {
fill: currentColor; /* the icon tints to match the link's text color too */
}Change .link-with-icon's color later — a rebrand, a dark theme, a hover
state — and the border and the SVG icon fill update automatically, because
both are defined relative to whatever color currently is rather than a
second hardcoded value that would otherwise drift out of sync.
Try it yourself
What to remember
- CSS colors: keyword, hex,
rgb()/rgba(),hsl()/hsla()— all interchangeable wherever a color is expected. - HSL separates hue, saturation and lightness, so holding hue/saturation fixed and varying lightness gives you a consistent set of shades — something hex and RGB don't make easy.
linear-gradient(direction, stop, stop, ...)generates a gradient with no image file; stops can be pinned to positions with percentages.background-size: cover/contain,background-position, andbackground-repeat: no-repeatcontrol how a background fills its box.currentColoralways resolves to the element's own text color — use it so a border, fill, or shadow stays in sync withcolorautomatically instead of duplicating the value.