silk.color.color.
Colors in the CSS Color 4 color spaces, with conversion, gamut mapping, mixing, adjustment, and contrast measurement.
When to use#
Use Color whenever a color is more than four channels to copy: to convert between sRGB,
Display P3, Oklch, Lab, HSL, and the other ColorSpace values, to interpolate gradient stops,
to derive hover and pressed shades of a theme color, or to check that text is readable on its
background. Use to to convert, toGamut or toRgba to get displayable channels,
mix to interpolate, lighten, darken, saturate, and rotateHue to adjust, and
contrastRatio to measure legibility.
Details#
A color is a ColorSpace, three components, and an alpha, all public and in f64. Components
use the CSS Color 4 reference ranges, except that percentages are fractions in [0, 1]:
RGB spaces (
Srgb,SrgbLinear,DisplayP3,A98Rgb,ProphotoRgb,Rec2020): red, green, and blue in[0, 1]inside the gamut.XyzD65andXyzD50: X, Y, and Z, with Y1for the reference white.Lab: lightness in[0, 100], then a and b, roughly in[-125, 125].Lch: lightness, chroma from0, then hue in degrees.Oklab: lightness in[0, 1], then a and b, roughly in[-0.4, 0.4].Oklch: lightness, chroma from0, then hue in degrees.Hsl: hue in degrees, saturation and lightness in[0, 1].Hwb: hue in degrees, whiteness and blackness in[0, 1].
A NaN component or alpha is a missing component, which CSS writes as none. Conversion reads a
missing component as zero. mix instead takes it from the other color, as CSS Color 4
interpolation requires. Conversion into a polar space marks the hue of an achromatic color, such
as white or gray, as missing, because no hue describes it.
Conversion goes through CIE XYZ with the D65 white point, using the matrices and transfer
functions of the CSS Color 4 sample code. Lab and ProPhoto use a D50 white and a Bradford
adaptation. Conversion never clips: a color outside the gamut of the target space gets
components outside [0, 1]. toGamut and toRgba map it into the gamut with the CSS Color
4 algorithm, which lowers Oklch chroma until the color fits and keeps lightness and hue.
Gotchas#
Missing components are NaN, so == on two components or a direct arithmetic step can give NaN.
Read a hue through isMissing first, or use approxEquals, which treats two missing
components as equal.
Examples#
Derive theme shades and check text contrast#
import silk.color.color { Color, ColorSpace, Interpolation }
pub fn main() -> i32 {
let brand = Color.fromHex(0x3366cc)
let hover = brand.lighten(0.08)
let border = brand.mix(Color.white(), 0.5, Interpolation.new(ColorSpace.Oklab))
if hover.space != ColorSpace.Srgb || border.space != ColorSpace.Oklab {
return 1
}
if Color.white().contrastRatio(brand) < 4.5 {
return 2
}
let channels = brand.to(ColorSpace.Oklch).toRgba()
if channels.b < 0.79 || channels.b > 0.81 {
return 3
}
return 0
}See also#
Use silk.color.rgba for plain straight or premultiplied channels, and silk.color.srgb for
the sRGB transfer function alone.
Import as Color with import silk.color.color { Color }.
Public declarations: 4.
ColorSpace#
pub enum ColorSpaceA color space from CSS Color 4: the meaning and range of the three components of a Color.
Details#
Each value names the space that CSS writes in color(), a color function, or an interpolation
method. Percentages are fractions here, so HSL saturation 50% is 0.5.
Srgb#
SrgbGamma-encoded sRGB: red, green, and blue in [0, 1]. The space of CSS hex colors and rgb().
SrgbLinear#
SrgbLinearsRGB primaries with linear-light channels in [0, 1], for physically correct blending.
DisplayP3#
DisplayP3Display P3: the wider gamut of modern displays, with the sRGB transfer function.
A98Rgb#
A98RgbAdobe RGB (1998), the a98-rgb space of CSS.
ProphotoRgb#
ProphotoRgbProPhoto RGB, a very wide gamut with a D50 white point.
Rec2020#
Rec2020ITU-R BT.2020 primaries with a 2.4 gamma, the rec2020 space of CSS.
XyzD50#
XyzD50CIE XYZ with the D50 white point.
XyzD65#
XyzD65CIE XYZ with the D65 white point, the hub of every conversion.
Lab#
LabCIE Lab (D50): lightness in [0, 100], then the a (green to red) and b (blue to yellow) axes.
Lch#
LchCIE LCh (D50): lightness in [0, 100], chroma from 0, and hue in degrees.
Oklab#
OklabOklab: perceptual lightness in [0, 1], then the a and b axes, roughly in [-0.4, 0.4].
Oklch#
OklchOklch: Oklab lightness in [0, 1], chroma from 0, and hue in degrees.
Hsl#
HslHSL over sRGB: hue in degrees, saturation and lightness in [0, 1].
Hwb#
HwbHWB over sRGB: hue in degrees, whiteness and blackness in [0, 1].
HueInterpolation#
pub enum HueInterpolationThe way mix interpolates hue in a polar space: the arc it takes around the hue circle.
Details#
The values match the hue interpolation methods of CSS Color 4. They have no effect when the interpolation space has no hue.
Shorter#
ShorterTakes the arc of at most 180 degrees, the CSS default.
Longer#
LongerTakes the arc of at least 180 degrees, the long way around.
Increasing#
IncreasingMoves toward increasing hue angles, wrapping from 360 to 0.
Decreasing#
DecreasingMoves toward decreasing hue angles, wrapping from 0 to 360.
Interpolation#
pub struct InterpolationThe color space and hue method in which mix interpolates two colors.
When to use#
Use Interpolation.new(ColorSpace.Oklab) for even gradients without hue shifts, which is the
CSS default. Use ColorSpace.Oklch to keep colors saturated through the middle of a gradient,
and ColorSpace.SrgbLinear to match physical light mixing.
Details#
The fields are public. A hue method only affects polar spaces: Lch, Oklch, Hsl, and Hwb.
Field space#
pub space: ColorSpaceThe color space in which components are interpolated, and the space of the result.
Field hue#
pub hue: HueInterpolationThe arc taken around the hue circle in a polar space.
Implementation Copy for Interpolation#
impl Copy for InterpolationImplementation Interpolation#
impl InterpolationAssociated function new#
pub fn new(space: ColorSpace) -> InterpolationReturns the interpolation in space with the shorter hue arc, the CSS default.
Associated function withHue#
pub fn withHue(space: ColorSpace, hue: HueInterpolation) -> InterpolationReturns the interpolation in space with the hue arc hue.
Color#
pub struct ColorA color: three components in a ColorSpace and an alpha.
When to use#
Use Color to convert between color spaces, map wide-gamut colors to a display, interpolate
gradient stops, derive shades, and measure contrast. Use silk.color.rgba.Rgba for channels
that only need to be stored or uploaded.
Details#
The fields are public. Component ranges depend on space: RGB spaces use [0, 1], Lab and
Lch lightness use [0, 100], Oklab and Oklch lightness use [0, 1], hues are in degrees,
and HSL and HWB percentages are fractions in [0, 1]. Alpha is in [0, 1] and straight, not
premultiplied.
A NaN component or alpha is missing, as CSS none: conversion reads it as zero and mix
takes the value from the other color. Conversion into a polar space marks the hue of an
achromatic color as missing.
Gotchas#
Two missing components are NaN and never compare equal with ==. Compare colors with
approxEquals.
Field space#
pub space: ColorSpaceThe color space that gives components their meaning.
Field components#
pub components: [f64; 3]The three components in the order CSS writes them for space. NaN marks a missing component.
Field alpha#
pub alpha: f64The opacity in [0, 1], straight rather than premultiplied. NaN marks a missing alpha.
Implementation Copy for Color#
impl Copy for ColorImplementation Color#
impl ColorAssociated function new#
pub fn new(space: ColorSpace, components: [f64; 3], alpha: f64) -> ColorReturns the color with components in space and opacity alpha.
Details#
The values are stored as given. Pass f64.NAN for a component that CSS would write as none.
Associated function srgb#
pub fn srgb(r: f64, g: f64, b: f64, alpha: f64) -> ColorReturns the gamma-encoded sRGB color with red r, green g, blue b, and opacity alpha,
each in [0, 1].
Associated function srgbLinear#
pub fn srgbLinear(r: f64, g: f64, b: f64, alpha: f64) -> ColorReturns the linear-light sRGB color with red r, green g, blue b, and opacity alpha,
each in [0, 1].
Associated function displayP3#
pub fn displayP3(r: f64, g: f64, b: f64, alpha: f64) -> ColorReturns the Display P3 color with red r, green g, blue b, and opacity alpha, each in
[0, 1].
Associated function hsl#
pub fn hsl(h: f64, s: f64, l: f64, alpha: f64) -> ColorReturns the HSL color with hue h in degrees, saturation s and lightness l in [0, 1],
and opacity alpha.
Gotchas#
Saturation and lightness are fractions: CSS hsl(210 50% 40%) is Color.hsl(210.0, 0.5, 0.4,
1.0).
Associated function hwb#
pub fn hwb(h: f64, w: f64, b: f64, alpha: f64) -> ColorReturns the HWB color with hue h in degrees, whiteness w and blackness b in [0, 1],
and opacity alpha.
Details#
When w + b is at least 1, the color is the gray w / (w + b) and the hue has no effect.
Associated function lab#
pub fn lab(l: f64, a: f64, b: f64, alpha: f64) -> ColorReturns the CIE Lab color with lightness l in [0, 100], axes a and b, and opacity
alpha.
Associated function lch#
pub fn lch(l: f64, c: f64, h: f64, alpha: f64) -> ColorReturns the CIE LCh color with lightness l in [0, 100], chroma c, hue h in degrees,
and opacity alpha.
Associated function oklab#
pub fn oklab(l: f64, a: f64, b: f64, alpha: f64) -> ColorReturns the Oklab color with lightness l in [0, 1], axes a and b, and opacity alpha.
Associated function oklch#
pub fn oklch(l: f64, c: f64, h: f64, alpha: f64) -> ColorReturns the Oklch color with lightness l in [0, 1], chroma c, hue h in degrees, and
opacity alpha.
When to use#
Use Oklch to author palettes: equal steps in lightness look equally spaced, and changing hue keeps perceived lightness.
Associated function fromHex#
pub fn fromHex(value: u32) -> ColorReturns the opaque sRGB color written in hex as 0xRRGGBB.
When to use#
Use fromHex for colors copied from a design tool, such as Color.fromHex(0x3366cc).
Gotchas#
Bits above the low 24 are ignored, so an 0xRRGGBBAA value gives the wrong color. Use
fromHexAlpha when the value has an alpha byte.
Associated function fromHexAlpha#
pub fn fromHexAlpha(value: u32) -> ColorReturns the sRGB color written in hex as 0xRRGGBBAA, whose low byte is the opacity.
Associated function parseHex#
pub fn parseHex(text: string) -> Option<Color>Returns the sRGB color of a CSS hex color, or None when text is not one.
Details#
Accepts three, four, six, or eight hex digits after an optional #, in either case: #rgb,
#rgba, #rrggbb, and #rrggbbaa. A short digit is repeated, so #f80 is #ff8800.
Associated function fromRgba#
pub fn fromRgba(rgba: Rgba<f64>) -> ColorReturns the gamma-encoded sRGB color with the straight-alpha channels of rgba.
Associated function fromLinearRgba#
pub fn fromLinearRgba(rgba: Rgba<f64>) -> ColorReturns the linear-light sRGB color with the straight-alpha channels of rgba.
Associated function black#
pub fn black() -> ColorReturns opaque sRGB black.
Associated function white#
pub fn white() -> ColorReturns opaque sRGB white.
Associated function transparent#
pub fn transparent() -> ColorReturns fully transparent sRGB black, the CSS transparent keyword.
Method isMissing#
pub fn isMissing(self: Self, index: usize) -> boolReturns true when component index, from 0 to 2, is missing (NaN).
Details#
A missing component is the CSS none value. Conversion into a polar space also marks the hue
of an achromatic color as missing.
Method withAlpha#
pub fn withAlpha(self: Self, alpha: f64) -> ColorReturns the color with the same space and components and opacity alpha.
Method to#
pub fn to(self: Self, space: ColorSpace) -> ColorReturns the color converted to space, without gamut mapping.
Details#
Missing components read as zero, and alpha is copied, including a missing alpha. A conversion
to the same space returns the color unchanged. A conversion into Lch, Oklch, Hsl, or
Hwb marks the hue missing when the color is achromatic. The result can lie outside the gamut
of space; use toGamut to bring it inside.
Conversion among Srgb, SrgbLinear, Hsl, and Hwb, between Lab and Lch, and between
Oklab and Oklch uses the direct formulas. Every other conversion goes through CIE XYZ
(D65).
Method inGamut#
pub fn inGamut(self: Self, space: ColorSpace) -> boolReturns true when the color lies inside the gamut of space, within 1e-9 per channel.
Details#
For an RGB space, every channel must be in [0, 1]. Hsl and Hwb use the sRGB gamut.
Lab, Lch, Oklab, Oklch, XyzD50, and XyzD65 hold every color, so the result is
true.
Method toGamut#
pub fn toGamut(self: Self, space: ColorSpace) -> ColorReturns the color converted to space and mapped into its gamut with the CSS Color 4
algorithm.
When to use#
Use toGamut before displaying a color from a wider space, such as an Oklch value with high
chroma or a Display P3 color on an sRGB screen.
Details#
A color already inside the gamut is converted exactly. Otherwise the algorithm keeps Oklch
lightness and hue, and searches for the largest chroma whose clipped color is within a just
noticeable difference (deltaEOK of 0.02) of the unclipped one. Lightness of 1 or more
maps to white and 0 or less to black. Hsl and Hwb map into the sRGB gamut. Spaces
without a gamut (Lab, Lch, Oklab, Oklch, XyzD50, XyzD65) return the plain
conversion. Alpha is copied unchanged.
Method toRgba#
pub fn toRgba(self: Self) -> Rgba<f64>Returns the straight-alpha gamma-encoded sRGB channels of the color, mapped into the sRGB gamut.
When to use#
Use toRgba to hand a color to a CSS-style renderer or to pack it into bytes. Use
toLinearRgba for linear-light blending and GPU pipelines.
Details#
The color is mapped with the CSS Color 4 gamut-mapping algorithm, so every channel is in
[0, 1]. A missing alpha becomes 1, and alpha is clamped to [0, 1].
Method toLinearRgba#
pub fn toLinearRgba(self: Self) -> Rgba<f64>Returns the straight-alpha linear-light sRGB channels of the color, mapped into the sRGB gamut.
When to use#
Use toLinearRgba for physically based blending and for GPU pipelines that render to an sRGB
surface format. Premultiply the result before compositing.
Details#
The color is mapped with the CSS Color 4 gamut-mapping algorithm, so every channel is in
[0, 1]. A missing alpha becomes 1, and alpha is clamped to [0, 1].
Method mix#
pub fn mix(self: Self, other: Color, t: f64, interpolation: Interpolation) -> ColorReturns the color t of the way from self to other, interpolated as CSS Color 4
specifies.
When to use#
Use mix for gradient stops, transitions, and blends between theme colors. t = 0.5 with
Interpolation.new(ColorSpace.Oklab) is CSS color-mix(in oklab, self, other).
Details#
The result is in interpolation.space. Both colors are converted to that space. A component
missing in one color takes the other's value, including a missing component carried over from
an analogous component of the original space, such as a missing hue or lightness. Components
are premultiplied by alpha (except hue), interpolated linearly, and divided by the
interpolated alpha. Hues follow interpolation.hue. t outside [0, 1] extrapolates.
Gotchas#
The result is not gamut mapped. Call toGamut or toRgba before display, because an
interpolation in Oklch or Lab can leave the sRGB gamut.
Method lighten#
pub fn lighten(self: Self, amount: f64) -> ColorReturns the color with Oklch lightness raised by amount, in the color's own space.
When to use#
Use lighten for hover states and lighter palette steps. Because Oklch lightness is
perceptual, the same amount looks like the same step for every hue.
Details#
The color is converted to Oklch, lightness becomes l + amount clamped to [0, 1], and the
result is converted back to the original space. Chroma and hue are unchanged, so a light,
saturated result can leave the gamut of an RGB space; call toGamut before display.
Method darken#
pub fn darken(self: Self, amount: f64) -> ColorReturns the color with Oklch lightness lowered by amount, in the color's own space.
When to use#
Use darken for pressed states and darker palette steps.
Details#
The color is converted to Oklch, lightness becomes l - amount clamped to [0, 1], and the
result is converted back to the original space. Chroma and hue are unchanged; call toGamut
before display.
Method saturate#
pub fn saturate(self: Self, amount: f64) -> ColorReturns the color with Oklch chroma raised by amount, in the color's own space.
Details#
The color is converted to Oklch, chroma becomes c + amount with a floor of zero, and the
result is converted back. Oklch chroma of saturated sRGB colors is about 0.1 to 0.32, so
useful amounts are small, such as 0.02. An achromatic color has no hue, so it gains chroma
toward a hue of zero (pink). The result can leave the gamut of an RGB space; call toGamut
before display.
Method desaturate#
pub fn desaturate(self: Self, amount: f64) -> ColorReturns the color with Oklch chroma lowered by amount, with a floor of zero, in the color's
own space.
Details#
The color is converted to Oklch, chroma becomes max(c - amount, 0), and the result is
converted back. Lightness and hue are unchanged.
Method rotateHue#
pub fn rotateHue(self: Self, degrees: f64) -> ColorReturns the color with its Oklch hue turned by degrees, in the color's own space.
Details#
The color is converted to Oklch, the hue becomes h + degrees wrapped into [0, 360), and
the result is converted back. An achromatic color is returned unchanged in value. Rotating by
180 gives the complementary color at the same lightness and chroma, which can leave the
gamut of an RGB space.
Method grayscale#
pub fn grayscale(self: Self) -> ColorReturns the gray with the same Oklch lightness, in the color's own space.
Details#
Oklch chroma becomes zero, so the result has the perceived lightness of the original. In a polar space the hue of the result is missing.
Method invert#
pub fn invert(self: Self) -> ColorReturns the sRGB negative of the color, in the color's own space.
Details#
The color is mapped into the sRGB gamut, each gamma-encoded channel becomes 1 - channel, and
the result is converted back. Alpha is unchanged. This matches the CSS invert(1) filter.
Method relativeLuminance#
pub fn relativeLuminance(self: Self) -> f64Returns the WCAG 2 relative luminance of the color, from 0 for black to 1 for white.
Details#
The color is mapped into the sRGB gamut, decoded to linear light, and weighted by
0.2126 R + 0.7152 G + 0.0722 B. Alpha is ignored; composite a translucent color over its
background first.
Method contrastRatio#
pub fn contrastRatio(self: Self, other: Color) -> f64Returns the WCAG 2 contrast ratio between the two colors, from 1 for equal luminance to 21
for black on white.
When to use#
Use contrastRatio to check text legibility. WCAG AA asks for at least 4.5 for body text
and 3 for large text and interface components; AAA asks for 7 and 4.5.
Details#
The ratio is (lighter + 0.05) / (darker + 0.05) of the two relative luminances, so the order
of the colors does not matter. Alpha is ignored; composite translucent colors first.
Method deltaEOK#
pub fn deltaEOK(self: Self, other: Color) -> f64Returns the CSS Color 4 deltaEOK difference: the Euclidean distance between the two colors
in Oklab.
When to use#
Use deltaEOK to ask whether two colors look the same. A value below 0.02 is about one just
noticeable difference.
Details#
Missing components read as zero. Alpha is ignored.
Method approxEquals#
pub fn approxEquals(self: Self, other: Color, tolerance: f64) -> boolReturns true when both colors are in the same space and every component and alpha differ by
at most tolerance.
Details#
Two missing components compare equal, and a missing component never equals a present one. Hues
compare around the circle, so 359.9 and 0.1 differ by 0.2. Colors in different spaces
are never equal; convert one with to first.
Category: Color.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.