Typing tomato or steelblue into a stylesheet is quick, readable and perfectly valid CSS. But HTML color names come with a long history and some odd quirks: darkgray is lighter than gray, several names are exact duplicates, and many named colors fail basic contrast checks. This guide covers where the 148 CSS color names came from, the original 16, the duplicates worth knowing, and when to use named colors versus design tokens.

What HTML Color Names Are

A CSS color name is a keyword that maps to one fixed sRGB value. color: crimson is exactly the same as color: #DC143C or color: rgb(220, 20, 60). Named colors work anywhere CSS accepts a color, in SVG attributes like fill="teal", and in the canvas API's fillStyle.

A few rules apply to every name:

  • They are case-insensitive. Red, RED and red are identical, though lowercase is the convention.
  • They are fully opaque. To make one transparent, use color-mix(in srgb, red 50%, transparent) or switch to rgb() with an alpha value.
  • They resolve to RGB. If you read a color back with getComputedStyle() in JavaScript, you get rgb(220, 20, 60), not crimson.
  • They are separate from transparent and currentColor. Those are special keywords and are not part of the 148-name list.

A Short History: From 16 Colors to 148

The named colors list grew in four stages:

  1. HTML 3.2 and HTML 4: 16 colors. The original names match the standard 16-color VGA palette of early Windows PCs, which is why they include blunt values like lime (#00FF00) and fuchsia (#FF00FF). CSS1 adopted the same 16 keywords.
  2. CSS 2.1: orange. orange (#FFA500) became the 17th keyword.
  3. CSS3 Color: the X11 names. CSS adopted the color keywords from SVG 1.0, which in turn came from the X11 Window System used on Unix workstations. That brought in names like papayawhip, lightgoldenrodyellow and mediumspringgreen, for a total of 147.
  4. CSS Color Level 4: rebeccapurple. The 148th name, #663399, was added in 2014 in memory of Rebecca Meyer, the young daughter of longtime CSS author Eric Meyer, who died on her sixth birthday.

Merging the HTML and X11 lists created conflicts. In X11, gray was #BEBEBE and green was #00FF00, but CSS kept the HTML values for the names it already had. Most of the oddities below trace back to that decision.

The 16 Original HTML Color Names

These are the names every browser has supported from the start, and they turn up constantly in documentation and quick prototypes.

NameHEXRGB
black#0000000, 0, 0
silver#C0C0C0192, 192, 192
gray#808080128, 128, 128
white#FFFFFF255, 255, 255
maroon#800000128, 0, 0
red#FF0000255, 0, 0
purple#800080128, 0, 128
fuchsia#FF00FF255, 0, 255
green#0080000, 128, 0
lime#00FF000, 255, 0
olive#808000128, 128, 0
yellow#FFFF00255, 255, 0
navy#0000800, 0, 128
blue#0000FF0, 0, 255
teal#0080800, 128, 128
aqua#00FFFF0, 255, 255

Notice that every channel uses only 00, 80, C0 or FF. That is a sign of their origin in a limited hardware palette, and it is why some of them, like lime and aqua, feel harsh in modern interfaces.

Duplicates and Quirks Worth Knowing

gray and grey

Every name containing "gray" also has a "grey" spelling with the identical value: gray, darkgray, dimgray, lightgray, slategray, lightslategray and darkslategray each have a "grey" twin. That is seven pairs. Pick one spelling for your codebase and stick to it, so searches and linting stay reliable.

aqua equals cyan, fuchsia equals magenta

aqua and cyan are both #00FFFF, and fuchsia and magenta are both #FF00FF. The HTML names and the X11 names described the same colors, so both were kept. Together with the seven gray/grey pairs, that means the 148 names cover only 139 distinct colors.

darkgray is lighter than gray

This is the most famous quirk. gray comes from HTML and is #808080. darkgray comes from X11 and is #A9A9A9, which is noticeably lighter. In X11, plain gray was lighter still, so "dark gray" made sense there; CSS kept the HTML value and broke the relationship. If you want something darker than gray, use dimgray (#696969).

green is not pure green

green is #008000, a medium green. The fully saturated #00FF00 is called lime. Expect the same mismatch if you assume a color name means the purest version of that hue.

Misspelled names fail silently

CSS does not throw an error for an unknown color name. A typo such as color: ligthgray makes the whole declaration invalid, so the browser simply ignores it and the element keeps its inherited or previously declared color. If a named color seems to have no effect, check the spelling in your browser's developer tools, which usually flag the declaration as invalid. Old HTML attributes such as bgcolor are even stranger: they use a lenient legacy parser that turns almost any string into some color, so a made-up word can render as a dark red instead of being rejected. Stick to CSS for colors and that problem never comes up.

Navigating All 148 CSS Color Names

The full list of CSS color names is not organized systematically. Prefixes like light, dark and medium are applied inconsistently, and names such as bisque, gainsboro and peru tell you little about the color. The easiest way to explore them is by family. The HTML color names tool shows all 148 in a searchable grid with HEX values and a color-family filter, plus a full name, HEX and RGB table; click any swatch to copy its HEX.

A few names hold up well in prototypes and demos:

NameHEXGood for
tomato#FF6347Warm accents and highlight blocks
dodgerblue#1E90FFPlaceholder primary color in mockups
seagreen#2E8B57Success states in demos
steelblue#4682B4Muted blue for charts and diagrams
slategray#708090Borders and icons (about 4.05:1 on white, so not small body text)
whitesmoke#F5F5F5Subtle background panels
crimson#DC143CError emphasis in prototypes
rebeccapurple#663399Deep purple accent

Going the other way, the color name finder takes any color and returns the nearest of the 148 named colors plus the five closest matches with their distance, and the color picker shows the nearest name for whatever you select. That is handy for readable code comments or for naming new tokens.

When Named Colors Are Fine

  • Prototypes and demos, where speed matters more than precision.
  • Debugging: outline: 2px solid red or background: yellow makes a layout box visible instantly.
  • Documentation and teaching, where color: navy is easier to read than a HEX code.
  • white and black, when you really do mean pure white and pure black.

When to Use Design Tokens Instead

For production interfaces, named colors cause problems as a product grows:

  • They carry no meaning. crimson describes a hue, not a role. When your error color changes, you have to hunt down every usage, while a token like --color-danger changes in one place.
  • They do not theme. A named color is identical in light and dark mode, while tokens can switch values per theme.
  • Many fail contrast. On a white background, gray text reaches about 3.95:1, below the 4.5:1 WCAG AA minimum for normal text; orange manages under 2:1 and yellow about 1.07:1. Test every pairing with the color contrast checker.
  • The palette is arbitrary. Named colors were never designed as a coherent scale, so combining them rarely produces a polished interface.

The fix is a small set of semantic custom properties with exact values. Named colors can still live in comments when they help:

:root {
  --color-text: #1F2937;
  --color-muted: #4B5563;
  --color-primary: #1D4ED8;
  --color-danger: #B91C1C; /* close to firebrick */
  --color-surface: #FFFFFF;
}

.alert-error {
  color: var(--color-danger);
}

For a complete approach, see how to name colors in a design system and how to build a color system for a startup from scratch.

Conclusion

HTML color names are a convenient shorthand: 148 case-insensitive keywords covering 139 distinct colors, supported everywhere CSS is. Learn the original 16, remember that darkgray is lighter than gray and that lime is the real pure green, and use names freely for prototypes and debugging. For production work, move to tokens with exact values that you can theme and test. Keep the HTML color names tool open whenever you need a quick reference.