Since May 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
The oklch() functional notation expresses a given color in the Oklab color space. oklch() is the cylindrical form of oklab(), using the same L axis, but with polar Chroma (C) and Hue (h) coordinates.
/* Absolute values */ oklch(40.1% 0.123 21.57) oklch(59.69% 0.156 49.77) oklch(59.69% 0.156 49.77 / .5) /* Relative values */ oklch(from green l c h / 0.5) oklch(from #123456 calc(l + 0.1) c h) oklch(from hsl(180 100% 50%) calc(l - 0.1) c h) oklch(from var(--color) l c h / calc(alpha - 0.1))
Below are descriptions of the allowed values for both absolute and relative colors.
Note: Usually when percentage values have a numeric equivalent in CSS, 100% is equal to the number 1. This is not the case for all of the oklch() component values. Here, 100% is equal to 0.4 for the C value.
oklch(L C H[ / A])
The parameters are as follows:
LA <number> between 0 and 1, a <percentage> between 0% and 100%, or the keyword none (equivalent to 0% in this case). In this case, the number 0 corresponds to 0% (black) and the number 1 corresponds to 100% (white). This value specifies the color's perceived lightness, or "brightness".
Note: The L in oklch() is the perceived lightness, which refers to the "brightness" we visually perceive with our eyes. This is different from the L in hsl(), where it represents lightness as compared to other colors.
CA <number>, a <percentage>, or the keyword none (equivalent to 0% in this case). This value is a measure of the color's chroma (roughly representing the "amount of color"). Its minimum useful value is 0, while the maximum is theoretically unbounded (but in practice does not exceed 0.5). In this case, 0% is 0 and 100% is the number 0.4.
HA <number>, an <angle>, or the keyword none (equivalent to 0deg in this case) representing the color's <hue> angle.
Note: The angles corresponding to particular hues differ across the sRGB (used by hsl() and hwb()), CIELAB (used by lch()), and Oklab (used by oklch()) color spaces. See the Hues in oklch() example below and the <hue> reference page for more details and examples.
A OptionalAn <alpha-value> representing the alpha channel value of the color, where the number 0 corresponds to 0% (fully transparent) and 1 corresponds to 100% (fully opaque). Additionally, the keyword none can be used to explicitly specify no alpha channel. If the A channel value is not explicitly specified, it defaults to 100%. If included, the value is preceded by a slash (/).
Note: See Missing color components for more information on the effect of none.
oklch(from <color> L C H[ / A])
The parameters are as follows:
from <color>The keyword from is always included when defining a relative color, followed by a <color> value representing the origin color: This is the original color that the relative color is based on. The origin color can be any valid <color> syntax, including another relative color.
LA <number> between 0 and 1, a <percentage> between 0% and 100%, or the keyword none (equivalent to 0% in this case). This represents the lightness value of the output color. Here the number 0 corresponds to 0% (black) and the number 1 corresponds to 100% (white).
CA <number>, a <percentage>, or the keyword none (equivalent to 0% in this case). This value represents the output color's chroma value (roughly representing the "amount of color"). Its minimum useful value is 0, while its maximum is theoretically unbounded (but in practice does not exceed 0.5). In this case, 0% is 0 and 100% is the number 0.4.
HA <number>, an <angle>, or the keyword none (equivalent to 0deg in this case) representing the output color's <hue> angle. See a sample of different hues in the Examples section below.
A OptionalAn <alpha-value> representing the alpha channel value of the output color, where the number 0 corresponds to 0% (fully transparent) and 1 corresponds to 100% (fully opaque). Additionally, the keyword none can be used to explicitly specify no alpha channel. If the A channel value is not explicitly specified, it defaults to the alpha channel value of the origin color. If included, the value is preceded by a slash (/).
When using relative color syntax inside an oklch() function, the browser converts the origin color into an equivalent Oklch color (if it is not already specified as such). The color is defined as three distinct color channel values — l (lightness), c (chroma), and h (hue) — plus an alpha channel value (alpha). These channel values are made available inside the function to be used when defining the output color channel values:
l channel value is resolved to a <number> between 0 and 1, inclusive.c channel value is resolved to a <number> between 0 and 0.4, inclusive.h channel value is resolved to a <number> between 0 and 360, inclusive.alpha channel is resolved to a <number> between 0 and 1, inclusive.When defining a relative color, the different channels of the output color can be expressed in several different ways. Below, we'll study some examples to illustrate these.
In the first two examples below, we are using relative color syntax. However, the first one outputs the same color as the origin color and the second one outputs a color not based on the origin color at all. They don't really create relative colors! You'd be unlikely to ever use these in a real codebase, and would probably just use an absolute color value instead. We included these examples as a starting point for learning about relative oklch() syntax.
Let's start with an origin color of hsl(0 100% 50%) (equivalent to red). The following function outputs the same color as the origin color — it uses the origin color's l, c, and h channel values (0.627966, 0.257704, and 29.2346) as the output channel values:
oklch(from hsl(0 100% 50%) l c h)
This function's output color is oklch(0.627966 0.257704 29.2346).
The next function uses absolute values for the output color's channel values, outputting a completely different color not based on the origin color:
oklch(from hsl(0 100% 50%) 42.1% 0.25 328.363)
In the above case, the output color is oklch(0.421 0.25 328.363).
The following function creates a relative color based on the origin color:
oklch(from hsl(0 100% 50%) 0.8 0.4 h)
This example:
hsl() origin color to an equivalent oklch() color — oklch(0.627966 0.257704 29.2346).H channel value for the output color to that of the origin oklch() equivalent's H channel value — 29.2346.L and C channel values to new values not based on the origin color: 0.8 and 0.4 respectively.The final output color is oklch(0.8 0.4 29.2346).
Note: As mentioned above, if the output color is using a different color model to the origin color, the origin color is converted to the same model as the output color in the background so that it can be represented in a way that is compatible (i.e., using the same channels).
In the examples we've seen so far in this section, the alpha channels have not been explicitly specified for either the origin or output colors. When the output color alpha channel is not specified, it defaults to the same value as the origin color alpha channel. When the origin color alpha channel is not specified (and it is not a relative color), it defaults to 1. Therefore, the origin and output alpha channel values are 1 for the above examples.
Let's look at some examples that specify origin and output alpha channel values. The first one specifies the output alpha channel value as being the same as the origin alpha channel value, whereas the second one specifies a different output alpha channel value, unrelated to the origin alpha channel value.
oklch(from hsl(0 100% 50% / 0.8) l c h / alpha) /* Computed output color: oklch(0.627966 0.257704 29.2346 / 0.8) */ oklch(from hsl(0 100% 50% / 0.8) l c h / 0.5) /* Computed output color: oklch(0.627966 0.257704 29.2346 / 0.5) */
In the following example, the hsl() origin color is again converted to the oklch() equivalent — oklch(0.627966 0.257704 29.2346). calc() calculations are applied to the L, C, H, and A values, resulting in an output color of oklch(0.827966 0.357704 9.23462 / 0.9):
oklch(from hsl(0 100% 50%) calc(l + 0.2) calc(c + 0.1) calc(h - 20) / calc(alpha - 0.1))
Note: Because the origin color channel values are resolved to <number> values, you have to add numbers to them when using them in calculations, even in cases where a channel would normally accept <percentage>, <angle>, or other value types. Adding a <percentage> to a <number>, for example, doesn't work.
<oklch()> =
oklch( [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ <hue> | none ] [ / [ <alpha-value> | none ] ]? )
<hue> =
<number> |
<angle>
<alpha-value> =
<number> |
<percentage>
This example shows the effect of varying the L (lightness) value of the oklch() functional notation.
<div data-color="blue-dark"></div> <div data-color="blue"></div> <div data-color="blue-light"></div> <div data-color="red-dark"></div> <div data-color="red"></div> <div data-color="red-light"></div> <div data-color="green-dark"></div> <div data-color="green"></div> <div data-color="green-light"></div>
[data-color="blue-dark"] {
background-color: oklch(10% 0.4 240);
}
[data-color="blue"] {
background-color: oklch(50% 0.4 240);
}
[data-color="blue-light"] {
background-color: oklch(90% 0.4 240);
}
[data-color="red-dark"] {
background-color: oklch(10% 0.4 20);
}
[data-color="red"] {
background-color: oklch(50% 0.4 20);
}
[data-color="red-light"] {
background-color: oklch(90% 0.4 20);
}
[data-color="green-dark"] {
background-color: oklch(10% 0.4 130);
}
[data-color="green"] {
background-color: oklch(50% 0.4 130);
}
[data-color="green-light"] {
background-color: oklch(90% 0.4 130);
}
The following example shows the effect of varying the C (chroma) value of the oklch() functional notation, with colors decreasing in intensity as the C value decreases from fully saturated to almost grey.
<div data-color="blue"></div> <div data-color="blue-chroma1"></div> <div data-color="blue-chroma2"></div> <div data-color="blue-chroma3"></div> <div data-color="red"></div> <div data-color="red-chroma1"></div> <div data-color="red-chroma2"></div> <div data-color="red-chroma3"></div> <div data-color="green"></div> <div data-color="green-chroma1"></div> <div data-color="green-chroma2"></div> <div data-color="green-chroma3"></div>
With the initial starting colors blue, red, and green, we declare progressively smaller values for chroma on them: starting from full color saturation at the high value of 0.4 (equivalent to 100%) down to 0.01 (equivalent to 2%), which is almost grey for all the colors.
[data-color="blue"] {
background-color: oklch(50% 0.4 240);
}
[data-color="blue-chroma1"] {
background-color: oklch(50% 0.2 240);
}
[data-color="blue-chroma2"] {
background-color: oklch(50% 0.1 240);
}
[data-color="blue-chroma3"] {
background-color: oklch(50% 0.01 240);
}
[data-color="red"] {
background-color: oklch(50% 100% 20deg);
}
[data-color="red-chroma1"] {
background-color: oklch(50% 50% 20deg);
}
[data-color="red-chroma2"] {
background-color: oklch(50% 25% 20deg);
}
[data-color="red-chroma3"] {
background-color: oklch(50% 2% 20deg);
}
[data-color="green"] {
background-color: oklch(50% 0.4 130);
}
[data-color="green-chroma1"] {
background-color: oklch(50% 0.2 130);
}
[data-color="green-chroma2"] {
background-color: oklch(50% 0.1 130);
}
[data-color="green-chroma3"] {
background-color: oklch(50% 0.01 130);
}
If we had used 0 instead of 0.01 and 2%, with the same lightness values, the colors would have all been the same shade of grey. In this example, they are almost grey.
The following example shows swatches with different H (hue) values of the oklch() functional notation.
<div data-color="0">0deg</div> <div data-color="20">20deg</div> <div data-color="40">40deg</div> <div data-color="60">60deg</div>
and so on.
[data-color="0"] {
background-color: oklch(50% 0.4 0deg);
}
[data-color="20"] {
background-color: oklch(50% 0.4 20deg);
}
[data-color="40"] {
background-color: oklch(50% 0.4 40deg);
}
[data-color="60"] {
background-color: oklch(50% 0.4 60deg);
}
and so on.
The hue angles in oklch() are different from those in hsl(). See <hue> for more information. In hsl(), the sRGB color 0deg represents red. However, in the CIELab color space, 0deg corresponds to magenta, while red is approximately 41deg.
The following example shows the effect of varying the A (alpha) value of the oklch() color function. The red and red-alpha elements overlap the #background-div element to demonstrate the effect of opacity. Giving A a value of 0.4 makes the color 40% opaque.
<div id="background-div"> <div data-color="red"></div> <div data-color="red-alpha"></div> </div>
[data-color="red"] {
background-color: oklch(50% 0.5 20);
}
[data-color="red-alpha"] {
background-color: oklch(50% 0.5 20 / 0.4);
}
This example styles three <div> elements with different background colors. The middle one is given the unmodified --base-color, while the left and right ones are given lightened and darkened variants of that --base-color.
These variants are defined using relative colors — the --base-color custom property is passed into an oklch() function, and the output colors have their lightness channel modified to achieve the desired effect via a calc() function. The lightened color has 0.15 (15%) added to the lightness channel, and the darkened color has 0.15 (15%) subtracted from the lightness channel.
:root {
--base-color: orange;
}
#one {
background-color: oklch(from var(--base-color) calc(l + 0.15) c h);
}
#two {
background-color: var(--base-color);
}
#three {
background-color: oklch(from var(--base-color) calc(l - 0.15) c h);
}
The output is as follows:
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
oklch |
111 | 111 | 113 | 97 | 15.4 | 111 | 113 | 75 | 15.4 | 22.0 | 111 | 15.4 |
mixed_type_parameters |
116 | 116 | 113 | 102 | 16.2 | 116 | 113 | 78 | 16.2 | 24.0 | 116 | 16.2 |
relative_syntax |
122119–122l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
122119–122l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
128 | 108105–108l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
1816.4–18Implementation based on older spec version. As a result, calculations withh channel values do not work correctly, requiring values to be specified with units (deg). |
122119–122l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
128 | 8179–81l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
1816.4–18Implementation based on older spec version. As a result, calculations withh channel values do not work correctly, requiring values to be specified with units (deg). |
26.025.0–26.0l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
122119–122l channel values incorrectly resolve to numbers between 0-100 rather than 0-1. As a result, channel value calculations require l values to be specified as percentage numbers without units (e.g. 20 for 0.2). See bug 40940488. |
1816.4–18Implementation based on older spec version. As a result, calculations withh channel values do not work correctly, requiring values to be specified with units (deg). |
<hue> data typelch() and oklab() color functions
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch