Lesson 3 of 12

CSS Colors and Backgrounds

Colour is usually the first thing people notice on a website. In CSS you can write the same colour in several formats, add transparency, and paint backgrounds with solid colours, images or gradients. This lesson on CSS colors and backgrounds shows each format, when to choose it, and how to keep text readable.

Where colour is used

The color property sets the text colour (and the default for borders and text decorations). background-color paints the area behind the content and padding. Other properties such as border-color, outline-color and accent-color (for checkboxes and radio buttons) also take colour values.

CSS colors in different formats

FormatExampleGood for
Named colourtomatoQuick tests and demos
Hex#1e6fd9, #1e6fd980Copying values from design tools like Figma
rgb()rgb(30 111 217)Thinking in red, green and blue channels
hsl()hsl(214 76% 48%)Making lighter or darker shades by hand
oklch()oklch(55% 0.18 255)Palettes where shades look evenly bright

Hex codes are pairs of hexadecimal digits for red, green and blue, from 00 to ff. HSL stands for hue (an angle on the colour wheel, 0 to 360), saturation and lightness, which is easier for humans: to make a hover state darker, you lower the lightness.

OKLCH (lightness, chroma, hue) is newer and supported in all modern browsers. Its lightness value matches how bright colours actually look to our eyes, so a blue and a yellow with the same lightness really do appear equally light. That makes it handy for building accessible colour scales.

Modern CSS writes colour functions with spaces instead of commas. The older comma syntax such as rgb(30, 111, 217) still works, so you will see both in real projects.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The same blue in five formats</title>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; }
.swatch {
  color: white;
  padding: 12px 16px;
  margin-block: 6px;
  border-radius: 6px;
}
.named { background-color: royalblue; }
.hex   { background-color: #1e6fd9; }
.rgb   { background-color: rgb(30 111 217); }
.hsl   { background-color: hsl(214 76% 48%); }
.oklch { background-color: oklch(55% 0.18 255); }
</style>
</head>
<body>
<div class="swatch named">royalblue</div>
<div class="swatch hex">#1e6fd9</div>
<div class="swatch rgb">rgb(30 111 217)</div>
<div class="swatch hsl">hsl(214 76% 48%)</div>
<div class="swatch oklch">oklch(55% 0.18 255)</div>
</body>
</html>

Transparency

Add an alpha value after a slash to make a colour see-through: rgb(0 0 0 / 50%) is half-transparent black. Hex supports alpha too with eight digits, for example #00000080. The keyword transparent is fully clear.

This is different from the opacity property. opacity: 0.5 fades the whole element, including its text and children, while an alpha colour fades only that one colour. For a translucent overlay with crisp text, use an alpha background.

Tip: The keyword currentColor means “whatever the text colour is”. Using it for borders or SVG icons keeps them matched to the text automatically, even on hover.

Background images and gradients

The background-image property accepts an image file with url() or a gradient. Gradients are generated by the browser, so they need no download and stay sharp at any size.

  • linear-gradient(to right, gold, orange) blends colours in a straight line. You can give a direction or an angle like 135deg.
  • radial-gradient(circle, white, skyblue) spreads outwards from a centre point.
  • background-size: cover scales an image to fill the box; contain fits the whole image inside it.
  • background-position: center and background-repeat: no-repeat control placement and tiling.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gradients and layered backgrounds</title>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; display: grid; gap: 16px; }

.sunrise {
  background-image: linear-gradient(135deg, #ffb347, #ff5e62);
  color: white;
  padding: 32px;
  border-radius: 12px;
}

.sea {
  background: radial-gradient(circle at top left, #e0f7ff, #0077b6);
  color: white;
  padding: 32px;
  border-radius: 12px;
}

.overlay {
  /* a translucent layer on top of a striped pattern */
  background:
    linear-gradient(rgb(0 0 0 / 55%), rgb(0 0 0 / 55%)),
    repeating-linear-gradient(45deg, #2a9d8f 0 20px, #e9c46a 20px 40px);
  color: white;
  padding: 32px;
  border-radius: 12px;
}
</style>
</head>
<body>
<div class="sunrise">Sunrise at Marina Beach</div>
<div class="sea">Backwaters of Alleppey</div>
<div class="overlay">Text stays readable on a busy background thanks to a semi-transparent overlay.</div>
</body>
</html>

In the last box, the background shorthand lists two layers separated by a comma. The first layer is drawn on top. A dark, semi-transparent gradient above a photo is a common trick to keep hero text readable.

Contrast and accessibility

Pretty colours are useless if people cannot read the text. WCAG asks for a contrast ratio of at least 4.5:1 for normal body text and 3:1 for large text. Light grey text on white often fails. Browser developer tools show the contrast ratio when you inspect a colour, so check it as you work.

Watch out: Never use colour as the only way to show meaning, for example a red border alone for an error. Add an icon or a text message too, so people with colour vision deficiency get the information.

A simple palette to start with

Beginners often pick too many colours. A small, consistent palette looks more professional. For most sites you need only:

  • One brand or accent colour for buttons and links, plus a darker shade for hover.
  • Two or three neutrals: a near-black for text, a mid-grey for secondary text and a light grey for borders and panels.
  • A few status colours: green for success, red for errors and amber for warnings.

Pure black text on pure white can feel harsh on large screens, so many designers use a very dark grey such as #1f2328 instead. Test the palette in both bright and dim light before you commit.

Later, in CSS Variables, you will store your CSS colors in custom properties so a brand colour is defined only once. Next up is the CSS Box Model, which explains how padding, borders and margins create space.

Further reading

Key takeaways

  • color sets text colour; background-color paints behind content and padding.
  • Colours can be named, hex, rgb(), hsl() or oklch(); HSL and OKLCH are easiest for building shades.
  • Add transparency with / alpha or 8-digit hex; opacity fades the whole element.
  • Gradients are background images; several layers can be stacked with commas.
  • Keep text contrast at 4.5:1 or more and never rely on colour alone.

Quick quiz

Check what you learned – pick an answer.

1. Which value is half-transparent black?

2. What is the difference between opacity: 0.5 and a semi-transparent background colour?

3. What minimum contrast ratio does WCAG AA require for normal-size body text?

Practice exercise

Build a banner that says "Diwali Sale" with a linear gradient from deep orange to gold at 90 degrees, white bold text, and a button whose background is a semi-transparent white using rgb() with alpha.

Show a hint

Use linear-gradient(90deg, …) and rgb(255 255 255 / 25%).

Show the solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gradient banner</title>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; }

.banner {
  background-image: linear-gradient(90deg, #e65100, #ffc107);
  color: white;
  font-weight: bold;
  padding: 32px;
  border-radius: 12px;
}

.banner button {
  background: rgb(255 255 255 / 25%);
  color: white;
  border: 1px solid white;
  padding: 8px 16px;
  border-radius: 6px;
  font: inherit;
}
</style>
</head>
<body>
<div class="banner">
  <h2>Diwali Sale</h2>
  <button>Shop now</button>
</div>
</body>
</html>

Progress is saved in this browser only.