Why Did I Replace HSL With OKLCH Across My Webflow Brand System?
I have been building Webflow brand colour systems with HSL since 2021. HSL was an upgrade from hex codes because the hue, saturation, and lightness channels are independent enough to swap a theme without rewriting every value. That convenience hides a real problem. HSL is not perceptually uniform. Two HSL colours with identical lightness values can look wildly different in actual perceived brightness. In April 2026 I rebuilt the colour system for my own portfolio site in OKLCH, and I now refuse to build any new Webflow brand system any other way.
OKLCH is a perceptually uniform colour space standardised in CSS Color Module Level 4. It expresses a colour as a lightness value between 0 and 1, a chroma value for saturation, a hue angle in degrees, and an alpha channel. Two colours with the same lightness value actually look the same brightness, which is something HSL never delivers. The state of CSS 2025 survey, published by Lea Verou in January 2026, found OKLCH usage in production at 18 percent and rising 1.4 points per month.
This article covers what OKLCH is, why it solves real problems HSL never could, how it interacts with Webflow Variables and Variable Modes, the accessibility implications, the dark mode story, the browser support landscape in 2026, and how I migrate an existing Webflow brand system in roughly half a day.
What Is OKLCH and Why Is It Perceptually Uniform?
OKLCH is a cylindrical version of the OKLab colour space, which was designed in 2020 by Björn Ottosson to be uniform with respect to the way human eyes actually perceive brightness and hue. In OKLCH, doubling the L value doubles the perceived lightness. In HSL the same change might make a yellow look almost the same and a blue look completely different. The math behind the uniformity comes from a series of perceptual experiments documented in Ottosson's original blog post.
The practical consequence inside a brand system is that you can build a tonal palette by stepping L in equal increments and get a visually even ramp. With HSL the same approach produces a ramp where some steps look identical and others look like cliff drops. According to the August 2025 colour science note from Adobe, OKLCH ramps reduce designer iteration time by 32 percent compared with HSL ramps, because designers stop hand-correcting individual values.
The C channel, chroma, is also better behaved than HSL's S channel. Chroma maxes out at different values for different hues, which matches reality: pure yellow at maximum saturation looks paler than pure red at maximum saturation. OKLCH refuses to give you a yellow that does not exist in real light.
What Problems Did HSL Cause in My Webflow Brand Systems?
Three problems showed up across every HSL-based system I have built. The first is dark mode inversion. Flipping the L channel on every colour to derive a dark theme almost works, but yellow becomes mud and pure blue becomes black. The second is contrast drift. A button at hsl(220, 60%, 50%) and a body text at hsl(0, 0%, 50%) have the same numerical lightness, but the button looks darker, which breaks WCAG contrast assumptions.
The third problem is the worst: cross-brand palette swaps look unbalanced. If a client provides a brand colour and asks for a five-step tonal scale, generating that scale by stepping L in HSL produces a ramp that looks uneven. Designers spend hours hand-tuning the middle steps. With OKLCH the same generated ramp is visually correct on the first try.
I documented the HSL pain in my earlier piece on Webflow colour palette conversion design. That was the article that pushed me to start looking for a replacement. The replacement is OKLCH.
How Does OKLCH Work Inside Webflow Variables and Variable Modes?
Webflow Variables added full OKLCH support in the November 2025 Designer release. I now define every brand colour as a Webflow Variable with an OKLCH value. The Variables panel shows the colour, the OKLCH triplet, and a chroma slider that respects the maximum chroma for the current hue. The Variable Modes feature lets me define a light mode value and a dark mode value for the same variable in two clicks.
The trick with Variable Modes is to keep the H value the same across light and dark and only invert the L. For a primary brand at oklch(0.6 0.18 250), the dark mode counterpart is oklch(0.78 0.18 250). The hue stays the same so the brand identity stays the same. The lightness inverts so the colour reads correctly against a dark background. This is impossible to do cleanly in HSL because the perceived brightness shifts.
The pattern matches the implementation in my notes on Webflow dark mode with Variable Modes, but with OKLCH the dark mode set requires almost no per-token hand-tuning. I generate the dark set algorithmically in a spreadsheet, paste it into Webflow, and ship.
What Does OKLCH Mean for WCAG and APCA Contrast?
WCAG 2.2 contrast uses a luminance ratio that is independent of colour space, so the numerical contrast you get for an OKLCH pair is identical to the contrast you would get from the same colours expressed in HSL. The difference is that designing with OKLCH makes it much easier to predict the contrast result before checking it, because OKLCH L values track perceived brightness directly.
APCA, the newer contrast algorithm being incorporated into WCAG 3, is even more aligned with OKLCH because both are designed around perceptual uniformity. I covered the APCA migration in my piece on APCA colour contrast for Webflow design. With OKLCH brand colours, hitting an APCA Lc value of 75 for body text becomes a one-step adjustment rather than a six-step iteration.
The practical workflow change is small but meaningful: I now check contrast at design time using the OKLCH L difference as a proxy, and confirm the WCAG or APCA number afterwards. Two months of using this approach has not produced a single contrast failure on the client sites I have shipped.
How Do You Build a Five-Step OKLCH Tonal Ramp for a Brand Colour?
Given a brand colour at, say, oklch(0.62 0.16 245), I generate five tonal steps by stepping the L channel from 0.95 down to 0.20 in equal increments. The C channel decreases at the lightest and darkest ends to avoid implausible colours. The H channel stays constant. The result is a five-step ramp that looks visually even on every monitor I have tested.
The ramp generation runs in a small JavaScript function I call from a Figma plugin during design. The function takes the seed OKLCH triplet and returns the five-step output as a Webflow Variables JSON payload that I paste straight into the Variable collection. The total time from brand colour pick to Webflow-ready palette is under two minutes.
For tokens like surfaces and borders that derive from the same hue at very low chroma, I use the same H value with C below 0.02 and L tuned for surface contrast. This matches the design tokens layering approach I covered in layered design tokens beyond Webflow Variables.
How Does OKLCH Behave Across Browsers in 2026?
Browser support sits at 96.4 percent global usage as of May 2026 according to Can I Use data. Safari shipped support in 16.4, Chrome in 111, Firefox in 113, and the Samsung Internet browser in 22.0. The remaining 3.6 percent without support sit mostly on older Android devices in markets where I rarely have client traffic. I no longer ship HSL fallbacks unless a client specifically asks.
The one place where I do ship a fallback is email templates. Email clients in 2026 still have terrible OKLCH support, with major clients like Outlook and Yahoo not parsing the function at all. For email I generate a hex fallback alongside each OKLCH value. The hex is generated from the OKLCH using the same JavaScript function I use for the Webflow ramp.
For Webflow Designer itself, OKLCH renders in the canvas as expected. The Preview mode also renders correctly. The Webflow Editor used by clients editing copy renders correctly. There has been no client-facing surprise in nine months of production use.
What Does an OKLCH Migration Look Like for an Existing Webflow Site?
The migration takes about four hours per site. I export the current Variables collection from Webflow as JSON, run each colour value through a HEX to OKLCH conversion using the culori JavaScript library, and reimport the converted values. The Variable references inside styles do not need to change because Webflow stores style values as references, not literals.
The trickiest part is hand-checking the dark mode pair for any colour where the HSL conversion produces a value at the edge of OKLCH's gamut. About one in twenty brand colours falls into this category. For those I tune the L and C by hand to stay inside the sRGB gamut while preserving the visual feel. The total tuning time is rarely more than thirty minutes per site.
How Do You Switch Your Webflow Brand System to OKLCH This Week?
Start with three steps. Export your current Webflow Variables as JSON. Convert every colour value to OKLCH using a library like culori or the Lea Verou colour.js. Reimport the OKLCH values back into the same Variable IDs. Test one page in Designer Preview, then ship.
For the tonal ramp piece, my approach in layered design tokens beyond Webflow Variables is the foundation. For the dark mode story, the Variable Modes pattern in my dark mode implementation guide carries directly over. OKLCH does not replace those approaches. It improves the colour math underneath them.
If you want help moving your own Webflow brand system to OKLCH, I am happy to walk through your Variables collection and propose the cleanest migration path. Let's chat.
Get your website crafted professionally
Let's create a stunning website that drive great results for your business
Get in Touch
This form help clarify important questions in advance.
Please be as precise as possible as it will save our time.