CSS color in CSS: hex, rgb, hsl, oklch, and picking the right format

The formats for writing a color in CSS (keyword, hex, rgb, hsl, oklch), where they apply, and the transparency trap.
4 min read
Believemy logo

No site ships without color, but writing one correctly in CSS has long been a source of confusion: the language accepts several different syntaxes for the exact same shade, and they are not interchangeable depending on what you plan to do with them.

This entry walks through the available formats, the properties a color can be applied to, and the most common trap: mixing up a fully opaque color with a transparent one.


Definition

In CSS, color has no property of its own: it is a value passed to any property that accepts one, such as color for text, background-color for a background, or border-color for an outline. The language offers several syntaxes for writing the same color, and none of them is objectively better: they simply answer different needs.


The available formats

A keyword (red, tomato, rebeccapurple) is the most readable, but it only covers the 148 names fixed by the specification. The hexadecimal format (#ff6600) is the most compact, and it is what most design tools hand you when you copy a swatch. The functions rgb() and hsl() describe a color through its components rather than an opaque code, which makes them easier to tweak by hand. A more recent function, oklch(), fixes a flaw shared by the two: it represents lightness changes in a way that matches human perception more evenly, so two shades that look close on paper no longer end up looking wildly different once rendered.

CSS
.primary-button {
  color: white;
  background-color: #ff6600;
}

.primary-button:hover {
  background-color: rgb(230 90 0);
}

.card {
  background-color: hsl(24 100% 50%);
  border: 1px solid oklch(70% 0.15 40);
}


Where a color can be applied

Color is not limited to text or backgrounds. It shows up in an element's outline, in a shadow, in a gradient, or in the focus ring shown when navigating with a keyboard. Any property whose documentation mentions a <color> value accepts any of the formats above, and you can freely mix formats across different properties in the same stylesheet.

FormatExampleWhen to use it
KeywordtomatoQuick prototyping, neutral colors
Hex#ff6600Color copied from a mockup
rgb()rgb(255 102 0)Readable components, transparency possible
hsl()hsl(24 100% 50%)Tweaking a shade by hand (lighter, darker)
oklch()oklch(70% 0.2 40)A perceptually consistent palette


Transparency is its own case

Keywords and the six-digit hex format allow no transparency at all: the color is fully opaque or it is not a color you can use. A partially transparent color needs a fourth channel, called the alpha channel. That is exactly the role of rgba() and hsla(), which adds that information without touching the rest of the layout.

Good to knowHex also accepts an eight-character notation (#ff660080) to bake in transparency, but it stays less readable than a four-value rgb(): save it for colors already generated automatically by a tool.


Best practices

Typing out the same color literally in fifteen different places is the first source of visual drift: a button that ends up slightly more orange than another, without anyone deciding it should be. The common practice is to centralize every color in a CSS custom property, then never write a literal value inside components themselves. A rebrand becomes a single edit instead of a search-and-replace hunt across the whole project. Our HTML and CSS course sets up this exact color variable system from the very first projects, building the habit before a site grows too large to do without it.


Frequently asked questions

QuestionWhy does a three-character hex color like #fff work?

Because each character is automatically doubled: #fff is exactly equivalent to #ffffff, and #039 is equivalent to #003399. This shorthand only works when both digits of each component are identical, which is not always true for an arbitrary color.

QuestionShould hsl() be preferred over rgb()?

It depends where the color comes from. If it comes from a mockup that gives red, green, blue values, rgb() avoids a conversion step. If you need to tweak a shade by hand, for example darkening a color on hover, hsl() is more intuitive: you only lower the third number, lightness, instead of recalculating three components at once.

QuestionCan the text color be reused for a border or an SVG icon?

Yes, without repeating it, thanks to a special keyword called currentColor. It automatically picks up the computed value of the element's color property, which avoids keeping two values in sync by hand whenever one of them changes.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.