Open any CSS stylesheet today, and you are likely to encounter colors declared in half a dozen different formats: #3B82F6, rgb(59, 130, 246), hsl(217, 91%, 60%), rebeccapurple, or the modern oklch(60% 0.2 250). While they can all refer to the exact same visual color on a user's monitor, each format represents a completely different way of organizing color data.
Choosing the right format is no longer just a matter of developer preference. It has direct implications for design system scalability, theme generation (like dark mode), animation performance, wide-gamut hardware utilization, and WCAG accessibility compliance.
In this guide, we will explore the inner workings of every major CSS color format, dissect the mathematical formulas behind color conversion, discover the historical quirks of named browser colors, and establish best practices for modern web stylesheets.
1. Convert Color Formats Online
Use our client-side tools to convert and inspect colors in real-time:
CSS Color Converter
Convert any color between HEX, RGB, HSL, CMYK, HWB and more. Copy each format.
Color Picker
Visual HEX/RGB/HSL color picker with sliders, history, and one-click copy.
2. Deep Dive: The CSS Color Formats
To understand why different formats exist, we must look at how browsers represent and render color. Let's explore the formats currently supported in CSS.
A. HEX (Hexadecimal notation)
HEX is the oldest and most widely used color notation on the web. It is a base-16 representation of the Red, Green, and Blue channels.
.element {
color: #3B82F6; /* 6-digit standard */
color: #3b82f6; /* Case-insensitive */
color: #38F; /* 3-digit shorthand (interprets as #3388FF) */
color: #3B82F680; /* 8-digit notation with 50% alpha transparency */
}
- How it works: A standard 6-digit hex code represents three pairs of hexadecimal values from
00(decimal 0) toFF(decimal 255). The first pair represents Red, the second Green, and the third Blue. - Pros: Extremely compact, universally supported, and the default output format for design tools like Figma and Adobe XD.
- Cons: Completely unreadable by humans. You cannot look at
#3B82F6and intuitively know that it is a medium-light blue, nor can you easily guess how to make it 10% darker without a calculator.
B. RGB and RGBA (Red, Green, Blue)
RGB represents colors as three separate channels using standard base-10 integers from 0 to 255 or percentages.
.element {
color: rgb(59, 130, 246); /* Legacy comma-separated */
color: rgba(59, 130, 246, 0.5); /* Legacy alpha variant */
color: rgb(59 130 246 / 50%); /* Modern CSS Level 4 comma-less syntax */
}
- How it works: It maps directly to how computer monitors emit light (mixing Red, Green, and Blue subpixels).
- Modern Syntax Note: Under the CSS Color Module Level 4 specification,
rgb()andrgba()have been merged. You no longer need to writergba(); the standardrgb()function now supports an optional alpha channel using a forward slash/syntax. - Pros: Direct mapping to display hardware, easy to manipulate programmatically, and simple to set transparency.
- Cons: Like HEX, it is difficult to read and adjust colors mentally.
C. HSL and HSLA (Hue, Saturation, Lightness)
HSL was introduced in CSS3 to bridge the gap between machine-readable RGB values and human intuition.
.element {
color: hsl(217, 91%, 60%);
color: hsl(217deg 91% 60% / 50%); /* Modern comma-less syntax with alpha */
}
It organizes color along three human-friendly axes:
- Hue: The position on the color wheel in degrees (
0to360).0degis red,120degis green, and240degis blue. - Saturation: The purity or intensity of the color, expressed as a percentage.
0%is completely desaturated (gray), and100%is the most vivid representation of that hue. - Lightness: The brightness of the color, expressed as a percentage.
0%is pure black,100%is pure white, and50%represents the pure, untinted color.
- Pros: Highly readable and intuitive. Generating hover states or active states is as simple as tweaking the Lightness value (e.g., subtracting 10% lightness to make a button look darker when pressed).
- Cons: Not perceptually uniform (see Section 3 below).
D. HWB (Hue, Whiteness, Blackness)
HWB is an alternative model proposed by Alvy Ray Smith (the co-founder of Pixar) in 1996. It is designed to match how humans mix paint.
.element {
color: hwb(217 23% 4%);
color: hwb(217 23% 4% / 50%);
}
- How it works: You start with a base Hue (0–360) and then specify how much Whiteness and Blackness to mix in.
- Pros: Highly intuitive for artistic designers who are used to adding white or black paint to a pure pigment to change its value.
- Cons: Limited browser usage and lack of familiarity among front-end developers.
E. OKLCH (Lightness, Chroma, Hue)
OKLCH is the modern successor to HSL, designed to utilize wide-gamut color spaces (like Display P3) while providing a perceptually uniform structure.
.element {
color: oklch(60% 0.2 250);
color: oklch(60% 0.2 250 / 80%);
}
It uses three axes:
- Lightness (L): The perceived brightness of the color, expressed as a percentage or decimal (
0%to100%or0to1). - Chroma (C): The saturation or purity of the color, roughly ranging from
0to a maximum of0.37depending on the hue and gamut. - Hue (H): The hue angle in degrees (
0to360), representing the color's wavelength.
3. The Power of Perceptual Uniformity: OKLCH vs. HSL
To understand why OKLCH is rapidly becoming the default color space for modern design systems, we must examine a fundamental flaw in the HSL model: it is not perceptually uniform.
In HSL, the "Lightness" channel is calculated using a simple mathematical average of the Red, Green, and Blue channels. However, human eyes do not perceive all wavelengths of light equally. We are significantly more sensitive to green and yellow light than to blue light.
Consider these two HSL declarations:
- Yellow:
hsl(60, 100%, 50%) - Blue:
hsl(240, 100%, 50%)
Both colors have an identical lightness value of 50%. However, if you look at them side by side, the yellow appears bright and glowing, while the blue looks deep and dark.
If you attempt to generate a color scale by adjusting the lightness of different hues in HSL, you will get inconsistent results:
Lightness 50% Yellow: hsl(60, 100%, 50%) -> Perceived as very bright (text needs to be dark)
Lightness 50% Blue: hsl(240, 100%, 50%) -> Perceived as dark (text needs to be white)
This makes programmatically generating accessible contrast pairs in HSL extremely difficult.
How OKLCH Solves the Problem
OKLCH is based on the OKLab color space, which is modeled on how the human brain and eyes actually process light.
If you set Lightness ($L$) to 60% in OKLCH, the resulting color will appear exactly as bright to the human eye, regardless of whether the hue angle points to yellow, green, or blue.
This perceptual uniformity allows developers to build robust, automated design systems:
- You can change the hue ($H$) of a component while guaranteeing that the contrast ratio against the background remains identical.
- You can generate accessible text-background pairings programmatically without manually auditing every single color variation.
- It supports colors outside the standard sRGB gamut, allowing Capable Wide-Gamut displays (like modern screens on MacBooks and iPhones) to render colors that are 30% more vibrant than those possible with standard HEX codes.
4. The Mathematics of Color Conversion
Let's review the mathematics required to convert color coordinates from one model to another.
A. Hexadecimal to RGB
Converting HEX to RGB involves translating base-16 characters into base-10 integers.
Let a HEX code be represented as $H = #R_1 R_2 G_1 G_2 B_1 B_2$. The decimal value of each channel is calculated as:
$$R = R_1 \times 16^1 + R_2 \times 16^0$$
$$G = G_1 \times 16^1 + G_2 \times 16^0$$
$$B = B_1 \times 16^1 + B_2 \times 16^0$$
Example: Converting `#3B82F6`
- Red Channel (
3B):
$$R = (3 \times 16) + 11 = 48 + 11 = 59$$ - Green Channel (
82):
$$G = (8 \times 16) + 2 = 128 + 2 = 130$$ - Blue Channel (
F6):
$$B = (15 \times 16) + 6 = 240 + 6 = 246$$
Thus, #3B82F6 converts to rgb(59, 130, 246).
B. RGB to HSL
To convert RGB to HSL, we first scale the $R$, $G$, and $B$ values to a range of $0$ to $1$:
$$r = \frac{R}{255}, \quad g = \frac{G}{255}, \quad b = \frac{B}{255}$$
Next, we identify the maximum and minimum values among these channels:
$$X_{\max} = \max(r, g, b), \quad X_{\min} = \min(r, g, b)$$
$$C = X_{\max} - X_{\min} \quad (\text{Chroma})$$
1. Calculating Lightness ($L$)
$$L = \frac{X_{\max} + X_{\min}}{2}$$
2. Calculating Saturation ($S$)
$$S = \begin{cases} 0 & \text{if } C = 0 \ \dfrac{C}{1 - |2L - 1|} & \text{if } C > 0 \end{cases}$$
3. Calculating Hue ($H$)
$$H = \begin{cases}
0^\circ & \text{if } C = 0 \
60^\circ \times \left(\dfrac{g - b}{C} \bmod 6\right) & \text{if } X_{\max} = r \
60^\circ \times \left(\dfrac{b - r}{C} + 2\right) & \text{if } X_{\max} = g \
60^\circ \times \left(\dfrac{r - g}{C} + 4\right) & \text{if } X_{\max} = b
\end{cases}$$
If $H$ is negative, add $360^\circ$ to normalize the degree value.
5. The History & Quirks of Named CSS Colors
In addition to mathematical color models, CSS supports 148 named color keywords (such as red, blue, papayawhip, and lavender). The origin of these names is filled with historical anomalies.
The X11 Legacy
The list of named colors does not originate from a W3C web design committee. Instead, it was inherited directly from the X11 Window System, an open-source graphical server built for Unix computers in the mid-1980s.
A small group of Unix developers compiled a text file mapping common English words to arbitrary RGB values. When early web browsers (like Mosaic and Netscape Navigator) needed named color keywords, they copied this X11 configuration file. The W3C later standardized this list in the CSS specification.
This inheritance led to several oddities that remain in browsers today to prevent breaking legacy web pages:
1. Why `darkgray` is Lighter than `gray`
In standard English, one would assume that a dark gray is darker than a standard gray. However, in CSS:
graymaps to#808080(exactly 50% brightness).darkgraymaps to#A9A9A9(approximately 66% brightness).
This bug occurred because the X11 color table had conflicting definitions, and the browser vendors resolved them incorrectly.
2. The Touching Story of `rebeccapurple`
One of the most modern and meaningful additions to the named color list is rebeccapurple (#663399).
In June 2014, Rebecca Meyer—the daughter of prominent web standards advocate and author Eric Meyer—passed away from brain cancer on her sixth birthday. Purple was her favorite color.
To honor her memory, the web community proposed adding the color #663399 to the official CSS specification under the name rebeccapurple. The W3C adopted the change unanimously. It remains one of the only browser-supported CSS colors named after a real person.
Finding Named Colors: The Euclidean Distance Formula
When you enter a custom HEX value in our Color Name Finder, it calculates which of the 148 standard keywords is the closest visual match. It does this using the 3D Euclidean distance formula.
We treat each color as a coordinate in a three-dimensional space where the axes are Red ($R$), Green ($G$), and Blue ($B$):
$$d = \sqrt{(R_1 - R_2)^2 + (G_1 - G_2)^2 + (B_1 - B_2)^2}$$
The named color with the smallest distance $d$ to your input is returned as the closest match. The maximum possible distance in this space is approximately 441.67 (the distance between pure black #000000 and pure white #FFFFFF).
6. Declaring Colors in Modern CSS: Syntax Best Practices
Web standards have consolidated color declarations to improve readability. Let's look at how you should write your color properties today.
A. Comma-less Functional Notation
Older specifications required writing comma-separated parameters: rgb(59, 130, 246). Modern CSS allows you to space-separate your parameters and declare alpha values using a slash:
/* Legacy */
.element {
background-color: rgba(59, 130, 246, 0.5);
}
/* Modern (CSS Color Level 4) */
.element {
background-color: rgb(59 130 246 / 50%);
}
B. Alpha Transparency in HEX
Instead of converting a HEX color to RGB just to add opacity, you can append a two-digit hexadecimal value (representing 0 to 255) to the end of your 6-digit hex string:
.card {
border: 1px solid #3B82F680; /* 50% opacity blue */
}
| Desired Opacity | Hex Suffix |
|---|---|
| 10% | 1A |
| 25% | 40 |
| 50% | 80 |
| 75% | BF |
| 90% | E6 |
| 100% | FF |
7. Structuring Colors in Modern Design Systems
For large-scale web applications, we recommend leveraging CSS custom properties (variables) to manage color scales. Using HSL or OKLCH is highly effective for this approach.
A. Creating Color Scales with HSL
By defining the Hue and Saturation once, you can generate a full range of tints and shades simply by altering the Lightness channel:
:root {
--primary-h: 217;
--primary-s: 91%;
/* Define systematic lightness values */
--blue-100: hsl(var(--primary-h) var(--primary-s) 95%);
--blue-500: hsl(var(--primary-h) var(--primary-s) 60%); /* Brand Base */
--blue-900: hsl(var(--primary-h) var(--primary-s) 20%);
}
.button {
background-color: var(--blue-500);
}
.button:hover {
background-color: var(--blue-900); /* Darker shade on hover */
}
B. Accessing Wide-Gamut Displays with Display P3
If your target audience uses modern screens (e.g., Apple hardware, high-end mobile devices), you can use media queries to serve wide-gamut colors to capable screens while falling back to standard sRGB colors for older displays:
:root {
--theme-vibrant: rgb(255 0 0); /* Fallback */
}
@media (color-gamut: p3) {
:root {
/* Serves a far more saturated red on capable screens */
--theme-vibrant: color(display-p3 1 0 0);
}
}
8. Summary: Quick Reference Guide
| Format | Syntax Example | Best For | Browser Support |
|---|---|---|---|
| HEX | #3B82F6 |
Copy-pasting static layout files from Figma. | Universal (100%) |
| RGB | rgb(59 130 246) |
Working with JavaScript animation engines. | Universal (100%) |
| HSL | hsl(217 91% 60%) |
Generating tints, shades, and dynamic themes. | Universal (100%) |
| OKLCH | oklch(60% 0.2 250) |
Modern, perceptually consistent design systems. | Modern (Chrome 111+, Safari 15.4+, Firefox 113+) |
By understanding the math, history, and structural mechanics of CSS colors, you can build cleaner stylesheets, establish flexible design system palettes, and ensure your websites look great on any display hardware.




