CSS Colors

▶ Try It Yourself

Color is one of the most expressive tools in CSS, and the language offers six distinct notations for defining it. Choosing the right color format affects readability, maintainability, and whether you can control transparency. In this lesson you will learn every CSS color format, understand when each is most appropriate, and build a reusable color palette using custom properties and HSL.

CSS Color Formats

Format Example Best Use Case
Named keywords color: tomato; Prototyping; semantic and self-documenting
HEX 6-digit #3b82f6 Design tool handoffs; universal support
HEX 8-digit #3b82f680 Transparency in HEX; last 2 digits = alpha
RGB / RGBA rgb(59 130 246 / .5) Programmatic manipulation; JS integration
HSL / HSLA hsl(217 91% 60%) Design systems; easy shade generation
currentColor border: 1px solid currentColor Inherit text color without repetition

Opacity vs Alpha Channel

Property / Notation What Becomes Transparent Affects Children?
opacity: 0.5 The entire element including text and children Yes — children inherit opacity
rgb(r g b / a) Only the color value it is applied to No — children unaffected
#rrggbbaa Only the color value it is applied to No — children unaffected

Understanding HSL

Component Range Description
Hue 0–360° Position on the color wheel (0=red, 120=green, 240=blue)
Saturation 0%–100% 0% = grey, 100% = fully vivid
Lightness 0%–100% 0% = black, 50% = normal, 100% = white
Note: Modern CSS (Color Level 4) accepts space-separated values: rgb(59 130 246 / 0.5). The slash separates the alpha. Both the old comma syntax rgba(59,130,246,0.5) and the new slash syntax work in all modern browsers.
Tip: Build your palette around HSL variables. Fix the hue, then generate shades by varying lightness from 95% (near-white) to 15% (near-black). One variable change shifts your entire brand color instantly.
Warning: Check color contrast for accessibility. Text must meet WCAG AA: 4.5:1 for body text, 3:1 for large text. Use the WebAIM Contrast Checker to verify your color choices.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Color Formats</title>
  <style>
    body { font-family: system-ui, sans-serif; padding: 24px; background: #f8fafc; }

    .swatch {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 150px;
      height: 90px;
      border-radius: 8px;
      margin: 8px;
      color: white;
      font-size: 0.75rem;
      font-weight: 600;
      text-shadow: 0 1px 3px rgba(0,0,0,0.4);
    }

    /* Named color */
    .s-named  { background: tomato; }

    /* 6-digit HEX */
    .s-hex    { background: #3b82f6; }

    /* 8-digit HEX with alpha */
    .s-hex-a  { background: #3b82f680; color: #1e40af; text-shadow: none; }

    /* RGB with alpha */
    .s-rgb    { background: rgb(59 130 246 / 0.75); }

    /* HSL */
    .s-hsl    { background: hsl(217 91% 60%); }

    /* Semi-transparent dark */
    .s-overlay {
      background: hsl(0 0% 0% / 0.4);
      border: 1px dashed #94a3b8;
      color: #1e293b;
      text-shadow: none;
    }
  </style>
</head>
<body>
  <div class="swatch s-named">Named: tomato</div>
  <div class="swatch s-hex">HEX: #3b82f6</div>
  <div class="swatch s-hex-a">HEX+A: 80</div>
  <div class="swatch s-rgb">RGB 75%</div>
  <div class="swatch s-hsl">HSL 217°</div>
  <div class="swatch s-overlay">Black 40%</div>
</body>
</html>

How It Works

Step 1 — Named Colors Are Keywords

CSS defines 140+ named colors. They map to fixed RGB values and improve readability but offer no shade or transparency control.

Step 2 — HEX Encodes RGB in Base-16

#3b82f6: red=3b(59), green=82(130), blue=f6(246). Adding two more digits: #3b82f68080 hex = 128 decimal ≈ 50% alpha.

Step 3 — RGB Gives Decimal Precision

rgb(59 130 246 / 0.75) = 75% opaque. The alpha affects only that specific color property, not child elements.

Step 4 — HSL Uses Human-Readable Axes

hsl(217 91% 60%): hue 217°(blue), saturation 91%(vivid), lightness 60%(medium). Changing lightness to 90% gives a very light sky blue; 20% gives a very dark navy.

Step 5 — currentColor Inherits Text Color

currentColor resolves to the element’s computed color value. A border or SVG fill using it stays in sync with text color automatically.

Real-World Example: Design-System Color Palette

/* design-tokens.css */
:root {
  --hue: 224;

  --primary-50:  hsl(var(--hue) 85% 97%);
  --primary-100: hsl(var(--hue) 82% 93%);
  --primary-200: hsl(var(--hue) 78% 85%);
  --primary-300: hsl(var(--hue) 74% 74%);
  --primary-400: hsl(var(--hue) 70% 63%);
  --primary-500: hsl(var(--hue) 70% 52%);
  --primary-600: hsl(var(--hue) 72% 43%);
  --primary-700: hsl(var(--hue) 76% 34%);
  --primary-800: hsl(var(--hue) 80% 26%);
  --primary-900: hsl(var(--hue) 84% 18%);

  --color-text:        var(--primary-900);
  --color-text-muted:  hsl(var(--hue) 20% 55%);
  --color-bg:          var(--primary-50);
  --color-surface:     #ffffff;
  --color-accent:      var(--primary-500);
  --color-accent-dark: var(--primary-700);
  --color-border:      var(--primary-200);

  --color-success: hsl(142 71% 45%);
  --color-warning: hsl(38  92% 50%);
  --color-danger:  hsl(0   84% 60%);
  --color-info:    hsl(199 89% 48%);
}

body { background: var(--color-bg); color: var(--color-text); font-family: system-ui, sans-serif; }

.btn-primary {
  background: var(--color-accent);
  color: #fff;
  padding: 10px 22px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 600;
}
.btn-primary:hover { background: var(--color-accent-dark); }

.alert-danger {
  background: hsl(0 84% 60% / 0.1);
  color: var(--color-danger);
  border-left: 4px solid var(--color-danger);
  padding: 12px 16px;
  border-radius: 0 6px 6px 0;
}

Common Mistakes

Mistake 1 — Invalid hex length

❌ Wrong — 5 digits is not a valid HEX format:

color: #3b82f; /* invalid */

✅ Correct — use 3, 4, 6, or 8 hex digits:

color: #3b82f6; /* valid 6-digit */
color: #38f;    /* valid 3-digit shorthand */

Mistake 2 — Using opacity instead of alpha for background only

❌ Wrong — text inside also becomes transparent:

.overlay { background: #000; opacity: 0.5; }

✅ Correct — use alpha on the background color only:

.overlay { background: rgb(0 0 0 / 0.5); }

Mistake 3 — Insufficient contrast

❌ Wrong — light grey on white fails WCAG AA (≈ 1.6:1 contrast):

p { color: #cccccc; background: #ffffff; }

✅ Correct — sufficient contrast (≈ 7:1):

p { color: #595959; background: #ffffff; }

▶ Try It Yourself

Quick Reference

Format Syntax Alpha Support
Named red, tomato No
HEX 6-digit #rrggbb No
HEX 8-digit #rrggbbaa Yes
RGB rgb(R G B) No
RGB with alpha rgb(R G B / A) Yes
HSL hsl(H S% L%) No
HSL with alpha hsl(H S% L% / A) Yes

🧠 Test Yourself

You want only the background to be 50% transparent without affecting text or child elements. Which is correct?





▶ Try It Yourself