Ways to define colors in CSS — from HEX to OKLCH 🎨
ColorsCSS has accumulated quite a few ways to describe color over the years. Some are familiar and compact, like #ff0000; some are practical and expressive, like rgb(255 0 0 / 0.5); and some are modern, powerful, and much better aligned with human perception—especially oklch().
If you write CSS today, it’s worth understanding not just how these formats work, but when each one makes sense. This article walks through the main color syntaxes in CSS, explains their strengths and trade-offs, and gives special attention to OKLCH, which is becoming one of the most visible parts of a website’s design, and CSS gives you several differentuseful ways to definework them. Some formats are compact, some are more human-friendly, and some are especially useful when transparency is involved.
In practice, all of these methods can describe the same visual result. The main difference is how you express thewith color andin whatmodern kinddesign of workflow it supports best.systems.
Why CSS has multipleso many color formats
CSSDifferent has evolved over time, and so have design workflows. Early web development relied heavily on simple notations like named colors and HEX values. Later,color formats like RGB, RGBA, HSL, and newer modern color functions were introduced to make colors easier to manipulate and reason about.
For example:
-
SystemsConvenienceand design tokens often use HEX because it is short and familiar.Modern UI work frequently uses alpha transparency for overlays, shadows, and subtle effects.
Named colors
CSS supports a set of predefined color names such aslike red, blue,are white,easy black,to gray,remember.
tomato,
h1design {
color: red;
}
body {
background-color: white;
}
Pros
Cons
Named colors are convenient, but they are usually not the best choice for production design systems where exact shades matter.
HEX colors
HEX is one of the most common color formats in CSS. It represents colors using hexadecimal digits, usually in the form #RRGGBB.
p {
color: #3366cc;
}
Here:Control
33Â represents the red component
66ccEach component ranges from 00Â to ff, which corresponds to decimal values from 0 to 255.
Short HEX
If each pair uses repeated digits, you can use the shorter 3-digit form:
color: #f0c;
This is equivalent to:
color: #ff00cc;
HEX with alpha
CSS also supports 8-digit HEX, where the last two digits define opacity:
background-color: #3366cc80;
You may also see the 4-digit shorthand version:
background-color: #f0c8;
Why HEX is popular
That said, HEX is not always the most intuitive format if you want to tweak brightness or create variations by hand.
RGB colors
The rgb() function defines a color using red, green, and blue channels.
color: rgb(51, 102, 204);
Each value typically ranges from 0 to 255.
This is the same color as:
color: #3366cc;
RGB can also use percentages:
color: rgb(20%, 40%, 80%);
Why RGB is useful
RGB is especially useful when colors come from JavaScript, design tools, or APIs that already provide channel-based values.
RGBA and alpha transparency
Originally, CSS used rgba()Â to define RGB colors with an alpha channel. Alpha controls transparency:
01background-color: rgba(51, 102, 204, 0.5);
Today, modern CSS also allows alpha directly in rgb()Â using slash syntax:
background-color: rgb(51 102 204 / 50%);
or
background-color: rgb(51 102 204 / 0.5);
This newer style is often preferred in modern CSS because it is more consistent with other color functions.
Common uses for alpha
HSL colors
The hsl() functionmake expressesit aeasier colorto think in termschannels.
Color science
Hue:Newerthe position on the color wheel, from 0 to 360
color: hsl(220 60% 50%);
This can make color adjustments feel more natural than editing RGB or HEX by hand.
For example, if you want a lighter version of a color, changing lightness is often easier than recalculating red, green, and blue values.
HSL with alpha
Like RGB, HSL can include transparency:
background-color: hsl(220 60% 50% / 0.5);
Why developersspaces like HSL
If you often adjust brightness, muted states, or hover colors manually, HSL can be especially comfortable.
HWB and newer CSS color functions
Modern CSS has introduced additional color formats, including hwb(), lab(), lch(), oklab(), and oklch(). Theseaim areto more advanced and are especially relevant for design systems, perceptualmake color consistency, and wide-gamut displays.
For example:
color: oklch(62% 0.16 260);
These newer formats are powerful, but they are still less common in everyday introductory CSS tutorials. Among them, OKLCHÂ has gained a lot of attention because it tends to match human perception better when adjusting color.
That means if you build a series of lighter and darker shades, the results may feel more visually consistent than with older formats.
Transparent and currentColor
Two special CSS color-related keywords are also worth knowing.
transparent
This means fully transparent:
border-color: transparent;
It is often used when you want an element to keep layout or border behavior without showing visible color.
currentColor
This keyword makes a property reuse the current value of the color property:
button {
color: #3366cc;
border: 2px solid currentColor;
}
This is very useful for icons, borders, and SVG elements that should automatically match surrounding text color.
Which format should you use?
There is no single correct answer 🙂. A lot depends on your project and preferences.
A practical rule of thumb is:
In manyshort: codebases,older youformats willare seestill useful, but newer ones are often better for design work that needs consistency and nuance.
Named colors
CSS supports a mixlong list of formats rather than just one.
A quick comparison
Here is the samepredefined color written in several common ways:keywords:
color: red;
background: rebeccapurple;
border-color: lightgray;
These are readable and quick, but they have limits:
Named colors are nice for demos, quick experiments, and a few memorable values like white, black, transparent, or rebeccapurple. For serious visual design, developers usually move to numeric color functions.
HEX colors
HEX is one of the most recognizable CSS color formats:
color: #ff0000;
color: #f00;
color:
These 0,two 0);values mean the same thing: pure red.
How HEX works
A 6-digit HEX color is structured like this:
#RRGGBB
Each pair is a channel from 00Â to ff:
RRÂ = red
GGÂ = green
BBÂ = blue
So:
#ff0000 /* red */
#00ff00 /* green */
#0000ff /* blue */
#ffffff /* white */
#000000 /* black */
There is also shorthand:
#f00 /* equivalent to #ff0000 */
#0f0 /* equivalent to #00ff00 */
#fff /* equivalent to #ffffff */
And alpha can be included too:
#ff000080 /* red at about 50% opacity */
#f008 /* shorthand with alpha */
When HEX is useful
HEX is popular because it is:
But it also has some drawbacks:
It’s not very intuitive for humans.
#7a5ccf doesn’t tell you much immediately.
Adjusting colors manually is awkward.
It reflects RGB encoding rather than human perception.
HEX is still common and totally valid, but it’s often best thought of as a storage or interchange format rather than the most ergonomic design format.
RGB and RGBA
RGB expresses colors through red, green, and blue channels:
color: rgb(255 0 0);
color: hsl(0rgb(255, 100%0, 50%)0);
AndBoth withforms transparency:are understood in CSS, though the space-separated modern syntax is generally preferred.
You can also include alpha:
color: rgba(255,rgb(255 0,0 0,0 0.5)/ 50%);
color: rgb(255 0 0 / 0.5);
Why RGB is useful
RGB maps directly to how screens emit light, so it is fundamental in digital color. It’s often useful when:
Example:
background-color: #ff000080;rgb(34 197 94 / 0.2);
That said, RGB has the same conceptual limitation as HEX: it is not a perceptual color space. Two colors with similar channel differences may not look similarly different.
HSL and HSLA
HSL stands for Hue, Saturation, Lightness:
color: hsl(0 100% 50%);
color: hsl(240 100% 50%);
color: hsl(120 100% 25% / 0.8);
Many developers like HSL because it feels more intuitive than RGB.
What the parts mean
Hue
0Â is red, 120Â is green, 240Â is blue.
Saturation
0%Â is gray, higher values are more colorful.
Lightness
0%Â is black, 100%Â is white.
Why HSL became popular
HSL is often easier to reason about when making quick adjustments:
/* same hue, different lightness */
--blue-40: hsl(220 80% 40%);
--blue-50: hsl(220 80% 50%);
--blue-60: hsl(220 80% 60%);
This looks appealing, but there is a catch: HSL lightness is not perceptually uniform. Colors with the same HSL lightness often do not appear equally bright. Yellow, for example, tends to look much brighter than blue at the same nominal lightness.
So HSL is intuitive, but it can be misleading when building balanced palettes.
HWB
CSS also supports hwb(), which means Hue, Whiteness, Blackness:
color: hwb(200 20% 10%);
This format is less common, but it can feel natural because it describes a hue mixed with white and black. It is useful in certain tooling and algorithmic color generation, though it has not become as mainstream as HEX, RGB, or HSL.
Lab and LCH
As CSS evolved, it began to support more perceptually oriented color spaces.
lab()
lab()Â is based on the CIE Lab color space:
color: lab(60% 30 20);
It uses:
lch()
lch()Â is a cylindrical representation of Lab:
color: lch(60% 50 30);
It uses:
This already feels more designer-friendly than lab(), because chroma and hue are easier to reason about than a and b.
Lab and LCH were important steps toward more perceptual CSS color handling, but in practice, OKLab and OKLCH are often even better choices.
OKLab and OKLCH — the modern highlight ✨
If there is one color format worth learning now, it is oklch().
Why OKLCH matters
OKLCH is built on OKLab, a color space designed to be more perceptually uniform than older RGB/HSL-style approaches and often more practical than CIE Lab/LCH for interface and web design.
The big promise is simple:
If you change a value in OKLCH, the visual result is more likely to match what you expected.
This is incredibly helpful for:
The structure of oklch()
An OKLCH color looks like this:
color: oklch(62% 0.18 264);
The three main components are:
Lightness
Chroma
Hue
Alpha can be added too:
color: oklch(62% 0.18 264 / 0.7);
Why designers and developers like OKLCH
1. Lightness behaves more sensibly
With HSL, equal lightness values across different hues often look inconsistent. In OKLCH, lightness is much closer to perceived lightness.
That means this kind of palette is more reliable:
--purple-40: oklch(40% 0.16 300);
--purple-55: oklch(55% 0.16 300);
--purple-70: oklch(70% 0.16 300);
Changing the first number tends to produce a more predictable visual ramp.
2. Chroma is better than “saturation” for many tasks
“Saturation” in HSL can be deceptive. A color at 100% saturation is not necessarily the most vivid or the most balanced version of that hue in practice.
In OKLCH, chroma is a more useful measure of colorfulness. If you reduce chroma, colors generally become more muted in a way that feels more natural:
--brand-strong: oklch(60% 0.22 250);
--brand-soft: oklch(60% 0.10 250);
These are easier to think about as “same lightness, same hue, different intensity.”
3. Hue shifts are easier to manage
Because OKLCH is designed for perceptual consistency, rotating hue while holding other values steady often gives more balanced results than in older spaces.
This is valuable for generating semantic palettes:
--info: oklch(65% 0.14 240);
--success: oklch(65% 0.14 145);
--warning: oklch(65% 0.14 85);
--danger: oklch(65% 0.14 25);
These colors are not magically perfect, but they often start from a much better baseline.
Reading OKLCH intuitively
A useful way to think about it is:
oklch(lightness chroma hue)
For example:
oklch(70% 0.12 210)
can be read as:
Over time, this becomes surprisingly ergonomic.
Practical examples
A button palette
:root {
--button-bg: oklch(62% 0.17 260);
--button-bg-hover: oklch(56% 0.17 260);
--button-text: oklch(98% 0.01 260);
}
This works well because:
A muted surface system
:root {
--surface-1: oklch(99% 0.01 250);
--surface-2: oklch(96% 0.01 250);
--surface-3: oklch(92% 0.02 250);
--text-1: oklch(22% 0.02 250);
--text-2: oklch(38% 0.02 250);
}
Notice how even “neutral” grays can carry a slight hue bias. That can make an interface feel warmer, cooler, softer, or more branded without becoming obviously colored.
Important caveat: gamut limits
OKLCH is excellent, but not every combination of lightness, chroma, and hue can be displayed on a typical screen. In other words, some values fall outside the available gamut.
This matters because:
So while OKLCH is powerful, it still has real-world limits. A practical workflow is to:
Alpha and transparency
Most modern CSS color functions support alpha using slash syntax:
rgb(0 0 0 / 0.5);
hsl(220 20% 20% / 0.3)
oklch(60% 0.15 240 / 0.4)
This is cleaner than older function pairs like rgba()Â and hsla(). While those names still exist historically, modern CSS treats alpha as a natural part of the same color function.
That consistency is one of the nice improvements in modern CSS syntax.
Choosing the right format
There is no single correct format for every situation. A sensible rule of thumb is:
Named colors
HEX
RGB
HSL
Lab/LCH
OKLCH
A few practical recommendations
If you’re building modern CSS today, here’s a pragmatic approach:
Use OKLCHÂ when you are defining a system of colors.
Use HEX or RGBÂ when integration or tooling makes them more convenient.
Be cautious with HSLÂ for palette construction.
Always test actual contrast and rendering.
Final thoughts
LearningCSS CSScolor has evolved from a handful of convenient notations into a genuinely rich system. HEX, RGB, and HSL are still useful and widely relevant, but they reflect older ways of thinking about color—more tied to encoding or simplified mental models than to human perception.
OKLCH stands out because it bridges technical precision and design intuition. It gives you a way to adjust lightness, intensity, and hue in a manner that much more closely matches what your eyes expect to see. For modern UI work, that makes it one of the most compelling color formats isCSS nothas justever about syntax—it is about choosing the representation that makes your work clearer and easier to maintain.offered.
If you areonly justtake startingone out,thing beginaway, withlet it be this: learn oklch(). Even if you continue using HEX, or RGB, in some places, understanding OKLCH will make you better at choosing, adjusting, and HSL. Once you are comfortable with those, exploring alpha channels and newerorganizing color spacesacross likethe OKLCH is a great next step 🚀board.