Every frontend project starts the same way.
:root {
--primary: #f59e0b;
--primary-hover: #d97706;
}
At first, it looks harmless.
Then the requirements grow.
:root {
--primary: #f59e0b;
--primary-hover: #d97706;
--primary-active: #b45309;
--primary-border: #ea9a00;
--primary-shadow: rgba(245, 158, 11, 0.2);
}
Somehow, one color became five.
And every time the design team changes the brand color, we repeat the same process:
- Open the color picker
- Make it darker for hover
- Make it even darker for active
- Adjust the shadow color
- Hope everything still looks consistent
I never questioned this workflow.
Until I discovered OKLCH.
The Problem We Pretend Doesn't Exist
Imagine our primary color is:
--primary: #ffa000;
Now we need a hover color.
What do we do?
Usually something like:
--primary-hover: #f29000;
But how did we get that value?
Most of the time:
- Trial and error
- Design tool adjustments
- Visual guessing
There is no real system.
We're manually creating color variations instead of describing how a color should change.
Then I Found This Weird Syntax
One day I came across this:
background: oklch(
from var(--primary)
calc(l - 0.05)
c
h
);
My first reaction:
Wait...
I can generate the hover color from the original color?
No extra color variable?
- Yes
What OKLCH Changed for Me
Instead of storing multiple versions of the same color:
--primary
--primary-hover
--primary-active
I only keep the source color:
--primary: oklch(0.75 0.18 70);
Then create variations on demand.
Hover:
background: oklch(
from var(--primary)
calc(l - 0.05)
c
h
);
Active:
background: oklch(
from var(--primary)
calc(l - 0.1)
c
h
);
Focus:
background: oklch(
from var(--primary)
calc(l + 0.05)
c
h
);
The color stays the same.
Only its lightness changes.
The Moment It Clicked
Traditional CSS asks:
What should the hover color be?
OKLCH asks:
How should the base color change?
That small shift in thinking makes a huge difference.
Before:
:root {
--success: #22c55e;
--success-hover: #16a34a;
--warning: #f59e0b;
--warning-hover: #d97706;
--error: #ef4444;
--error-hover: #dc2626;
}
After:
:root {
--success: oklch(...);
--warning: oklch(...);
--error: oklch(...);
}
And every hover color is generated automatically:
button:hover {
background: oklch(
from var(--button-color)
calc(l - 0.05)
c
h
);
}
No duplicate color tokens & No maintenance burden.
Tailwind Is Already Doing This
Many developers still think in HEX and RGB.
The industry isn't moving toward OKLCH because the syntax is cool.
It's moving toward OKLCH because generating color variations mathematically is more reliable than manually picking dozens of related colors.
The Hidden Benefit During Rebranding
Imagine the design team changes the primary color.
Before:
All need review.
After:
Change one value.
Everything derived from it updates automatically.
Hover, Active, Focus, Shadows, Borders, and Glows.
All stay consistent.
Top comments (0)