Colours as maps, converted between the colour spaces of CSS Color 4.
A colour is a map of its :space, its :coords and its :alpha, e.g. {:space :oklch :coords [0.44 0.085 158.0] :alpha 1.0}, the shape that Colour.js uses. A missing component, which CSS writes as none, is nil. Every function of the library takes a CSS colour as well, e.g. "#24476b" or "oklch(44% 0.085 158)", which syntax/parse reads.
The spaces are those of CSS Color 4, by these ids: :srgb, :srgb-linear, :display-p3, :display-p3-linear, :a98-rgb, :prophoto-rgb, :rec2020, :xyz-d65, :xyz-d50, :lab, :lch, :oklab, :oklch, :hsl and :hwb. Their coordinates have the ranges of CSS's sample code: red, green and blue from 0 to 1, the saturation and lightness of HSL from 0 to 100, the lightness of Lab and LCH from 0 to 100, and of Oklab and OKLCH from 0 to 1, and hues in degrees.
The other namespaces build on this one:
Colours as maps, converted between the colour spaces of CSS Color 4.
A colour is a map of its :space, its :coords and its :alpha, e.g.
{:space :oklch :coords [0.44 0.085 158.0] :alpha 1.0}, the shape that
Colour.js uses. A missing component, which CSS writes as none, is nil. Every function of
the library takes a CSS colour as well, e.g. "#24476b" or
"oklch(44% 0.085 158)", which syntax/parse reads.
The spaces are those of CSS Color 4, by these ids: :srgb, :srgb-linear,
:display-p3, :display-p3-linear, :a98-rgb, :prophoto-rgb, :rec2020,
:xyz-d65, :xyz-d50, :lab, :lch, :oklab, :oklch, :hsl and :hwb. Their
coordinates have the ranges of CSS's sample code: red, green and blue
from 0 to 1, the saturation and lightness of HSL from 0 to 100, the
lightness of Lab and LCH from 0 to 100, and of Oklab and OKLCH from 0 to
1, and hues in degrees.
The other namespaces build on this one:
- space, syntax, gamut, contrast, difference and mix, the rest of the
core
- choose, harmony, tone and target, ways to choose and generate colours
- quantise and image, the colours of an image
- vision, colours as people with a colour vision deficiency see them
- theme, the colours of a site or an app, from one colour or one imageColours chosen from among others, e.g. from the palette of an image or from colours that a designer made.
Colours chosen from among others, e.g. from the palette of an image or from colours that a designer made.
The contrast of two colours by WCAG 2.2, and the text colour that reads best on one.
WCAG 2.2 asks for these contrast ratios:
The ratio overstates the contrast of dark colours, which APCA addresses. APCA's licence forbids changing it and using it commercially, so it isn't here, but any function of two colours can stand in for ratio where an app wants its own measure.
The contrast of two colours by WCAG 2.2, and the text colour that reads best on one. WCAG 2.2 asks for these contrast ratios: - 4.5 for text, and 3 for large text, i.e. 18 points, or 14 points bold (success criterion 1.4.3) - 3 for the parts of a control and for graphics (1.4.11) - 7 and 4.5 at level AAA (1.4.6) The ratio overstates the contrast of dark colours, which APCA addresses. APCA's licence forbids changing it and using it commercially, so it isn't here, but any function of two colours can stand in for ratio where an app wants its own measure. https://www.w3.org/TR/WCAG22/#dfn-contrast-ratio
How different two colours look, by the measures of colour difference that CSS Color 4 gives, in section 20.
How different two colours look, by the measures of colour difference that CSS Color 4 gives, in section 20. - delta-e, the distance in Oklab, ΔEOK, of which 0.02 is about the least difference that shows - delta-e-ok2, ΔEOK with a and b doubled, which Ottosson found to fit the data of perceived differences better - delta-e-76, the distance in CIELAB, CIE76, of which 2.3 is about the least that shows (Sharma and Trussell 1997) - delta-e-2000, CIEDE2000, the standard of the CIE, of which 1 to 2 is about the least that shows https://www.w3.org/TR/css-color-4/#color-difference
Whether a colour lies in the gamut of a space, and the nearest colour that does.
There are three ways to bring a colour into a gamut:
Whether a colour lies in the gamut of a space, and the nearest colour that does. There are three ways to bring a colour into a gamut: - to-gamut, the gamut mapping of CSS Color 4, lowers its chroma in OKLCH at the same lightness and hue - clip clamps each channel, which shifts the lightness and the hue a little, but is what browsers still do (csswg-drafts issue 9449) - reduce-chroma lowers its chroma in a polar space of your choice, e.g. LCH, and keeps that space's lightness and hue exactly https://www.w3.org/TR/css-color-4/#gamut-mapping
Colours of related hues: the classical harmonies of the colour wheel, turned in OKLCH unless a space is given.
The harmonies go back to Itten (The Art of Color, 1961), whose wheel is the painter's. Turned in OKLCH, a colour keeps its lightness and its chroma, while a turn of HSL's hue changes how light a colour looks (Ottosson, A perceptual color space for image processing, 2020). The evidence for the harmonies is mixed: Schloss and Palmer (2011) found that people rate pairs of similar hues as more harmonious, but prefer a figure whose hue contrasts with its ground. https://bottosson.github.io/posts/oklab/ https://pmc.ncbi.nlm.nih.gov/articles/PMC3037488
Colours of related hues: the classical harmonies of the colour wheel, turned in OKLCH unless a space is given. The harmonies go back to Itten (The Art of Color, 1961), whose wheel is the painter's. Turned in OKLCH, a colour keeps its lightness and its chroma, while a turn of HSL's hue changes how light a colour looks (Ottosson, A perceptual color space for image processing, 2020). The evidence for the harmonies is mixed: Schloss and Palmer (2011) found that people rate pairs of similar hues as more harmonious, but prefer a figure whose hue contrasts with its ground. https://bottosson.github.io/posts/oklab/ https://pmc.ncbi.nlm.nih.gov/articles/PMC3037488
The colours of an image, e.g. a podcast's artwork, from the bytes of its file, for an app to colour its UI by, and small copies of the image.
The platform decodes the image at a small size: ImageIO on the JVM, and the browser's own decoder in ClojureScript. On the JVM each function returns its result, and in ClojureScript a promise of it. The result is nil where the platform can't decode the image, e.g. WebP on the JVM, or anything in Node, which has no decoder, and for an image that's all transparent.
(cc/hex (image/seed bytes)) ; e.g. "#24476b"
For the theme of a whole site or app from an image, see theme/from-image. For small copies of an image, e.g. of artwork for a list, see thumbnails.
The colours of an image, e.g. a podcast's artwork, from the bytes of its
file, for an app to colour its UI by, and small copies of the image.
The platform decodes the image at a small size: ImageIO on the JVM, and
the browser's own decoder in ClojureScript. On the JVM each function
returns its result, and in ClojureScript a promise of it. The result is
nil where the platform can't decode the image, e.g. WebP on the JVM, or
anything in Node, which has no decoder, and for an image that's all
transparent.
(cc/hex (image/seed bytes)) ; e.g. "#24476b"
For the theme of a whole site or app from an image, see
theme/from-image. For small copies of an image, e.g. of artwork for a
list, see thumbnails.The conversion and interpolation of colour maps by the rules of CSS Color 4, which syntax uses for color-mix(), and mix for the rest.
A colour here is a map of its :space, :coords and :alpha, which these functions don't check. https://www.w3.org/TR/css-color-4/#interpolation
The conversion and interpolation of colour maps by the rules of CSS Color 4, which syntax uses for color-mix(), and mix for the rest. A colour here is a map of its :space, :coords and :alpha, which these functions don't check. https://www.w3.org/TR/css-color-4/#interpolation
Colours between colours, interpolated by the rules that CSS Color 4 gives gradients and color-mix():
Colours between colours, interpolated by the rules that CSS Color 4 gives gradients and color-mix(): - in Oklab, unless a space is given - with premultiplied alpha - with a missing component taken from the other colour - with a hue that turns the shorter way round, unless a method says otherwise https://www.w3.org/TR/css-color-4/#interpolation
The few colours that stand for the many pixels of an image.
The pixels are a sequence of vectors of red, green, blue and alpha from 0 to 255, as image/pixels, a canvas or ImageIO gives them. Only the opaque ones count, with an alpha of 128 or more. Each function returns maps of a :colour and its :share of the opaque pixels, the largest share first.
The few colours that stand for the many pixels of an image. The pixels are a sequence of vectors of red, green, blue and alpha from 0 to 255, as image/pixels, a canvas or ImageIO gives them. Only the opaque ones count, with an alpha of 128 or more. Each function returns maps of a :colour and its :share of the opaque pixels, the largest share first.
The colour spaces of CSS Color 4 as data, and the conversion of coordinates between them.
A space is a map of its :id, its :coords, its :base, and the functions :to-base and :from-base, which convert a vector of coordinates to and from those of the base. Each space's chain of bases ends at xyz-d65, the only space without a base. A conversion goes up one space's chain to the first space that the other's chain shares, then down the other's.
Each coordinate is a map of these:
The matrices and transfer functions are those of CSS Color 4's sample code, section 19, under the W3C Software and Document License: https://www.w3.org/TR/css-color-4/#color-conversion-code
The colour spaces of CSS Color 4 as data, and the conversion of coordinates between them. A space is a map of its :id, its :coords, its :base, and the functions :to-base and :from-base, which convert a vector of coordinates to and from those of the base. Each space's chain of bases ends at xyz-d65, the only space without a base. A conversion goes up one space's chain to the first space that the other's chain shares, then down the other's. Each coordinate is a map of these: - :id - :range, which a percentage of CSS is a share of - :category, the coordinates of other spaces it's analogous to, which interpolation uses - :angle?, true for a hue The matrices and transfer functions are those of CSS Color 4's sample code, section 19, under the W3C Software and Document License: https://www.w3.org/TR/css-color-4/#color-conversion-code
CSS colours, parsed from the syntax of CSS Color 4 and 5, and serialised by the rules of CSS Color 4.
The parser reads:
It doesn't read relative colours, calc() or system colours. https://www.w3.org/TR/css-color-4/ https://www.w3.org/TR/css-color-5/#color-mix
CSS colours, parsed from the syntax of CSS Color 4 and 5, and serialised by the rules of CSS Color 4. The parser reads: - hex colours, the named colours and transparent - rgb(), rgba(), hsl(), hsla(), hwb(), lab(), lch(), oklab(), oklch() and color(), in the modern syntax and the legacy one with commas, with none for a missing component - color-mix(), of any number of colours It doesn't read relative colours, calc() or system colours. https://www.w3.org/TR/css-color-4/ https://www.w3.org/TR/css-color-5/#color-mix
Colours found by the contrast that they should have, by the method of Adobe's Leonardo: a search for the lightness at which a colour has the contrast asked for with a background, since the same lightness has a different contrast at each hue. https://github.com/adobe/leonardo
Colours found by the contrast that they should have, by the method of Adobe's Leonardo: a search for the lightness at which a colour has the contrast asked for with a background, since the same lightness has a different contrast at each hue. https://github.com/adobe/leonardo
The colours of a site or an app from one colour or one image, light and dark, checked for contrast, as CSS or as hex.
(def t (from-seed "#24476b")) ; or (from-image bytes)
(css t) ; custom properties for a web page
(:dark (hex t)) ; a map of hex colours, e.g. for React Native
(remove :ok? (report t))
A theme has ten roles, in words that a beginner knows:
Each role is a token of tone in LCH, so its lightness is CIELAB's L*, like the tones of Material 3. Each pair that must contrast keeps its contrast, to within a few percent, whatever the seed's hue, and the lightness of each role leaves a margin for that. The accent, the link and the focus ring take the seed's hue and chroma, and the rest a hint of its hue, like the greys that Radix pairs with an accent.
There are two levels of contrast, :standard and :more, like those of Material 3 and Apple. The function css writes :more for prefers-contrast: more.
A theme is plain data, so you can set a role by hand, e.g. with assoc-in, and report checks it again. https://github.com/material-foundation/material-color-utilities/blob/main/concepts/contrast_for_accessibility.md https://www.radix-ui.com/themes/docs/theme/color
The colours of a site or an app from one colour or one image, light and
dark, checked for contrast, as CSS or as hex.
(def t (from-seed "#24476b")) ; or (from-image bytes)
(css t) ; custom properties for a web page
(:dark (hex t)) ; a map of hex colours, e.g. for React Native
(remove :ok? (report t))
A theme has ten roles, in words that a beginner knows:
- :background, the page, and :surface, a panel or a card on it
- :text, and :text-muted for what matters less, e.g. a date
- :border, the edge of a control, e.g. a field, and :divider, a line
between parts that marks nothing
- :accent, the fill of the main control, e.g. a button, and :on-accent,
the text on it
- :link, the colour of a link, and :focus, the ring of the focused
control
Each role is a token of tone in LCH, so its lightness is CIELAB's L*,
like the tones of Material 3. Each pair that must contrast keeps its
contrast, to within a few percent, whatever the seed's hue, and the
lightness of each role leaves a margin for that. The accent, the link and
the focus ring take the seed's hue and chroma, and the rest a hint of its
hue, like the greys that Radix pairs with an accent.
There are two levels of contrast, :standard and :more, like those of
Material 3 and Apple. The function css writes :more for
prefers-contrast: more.
A theme is plain data, so you can set a role by hand, e.g. with assoc-in,
and report checks it again.
https://github.com/material-foundation/material-color-utilities/blob/main/concepts/contrast_for_accessibility.md
https://www.radix-ui.com/themes/docs/theme/colorColours from one seed, each at a fixed lightness, so that their contrast holds whatever the seed's hue.
A token is a map of these, e.g. {:l 0.33 :c 0.1 :turn 180}, which CSS writes as oklch(from var(--seed) 33% min(c, 0.1) calc(h + 180)):
In :lch, the lightness is CIELAB's L*, like the tones of Material 3. L* follows WCAG's luminance, but for CIELAB's adaptation to the white of D50, so a pair of tokens keeps its contrast at every hue, to within a few percent for vivid colours and less for near-greys. In :oklch, the hues look more even, but the contrast varies more with the hue. The function worst-contrast says how far it goes. https://github.com/material-foundation/material-color-utilities/blob/main/typescript/hct/hct.ts
Colours from one seed, each at a fixed lightness, so that their contrast
holds whatever the seed's hue.
A token is a map of these, e.g. {:l 0.33 :c 0.1 :turn 180}, which CSS
writes as oklch(from var(--seed) 33% min(c, 0.1) calc(h + 180)):
- :space, its polar space, by default :oklch
- :l, its lightness in that space
- :c, the most chroma that it takes from the seed
- :turn, the degrees that its hue turns from the seed's
In :lch, the lightness is CIELAB's L*, like the tones of Material 3. L*
follows WCAG's luminance, but for CIELAB's adaptation to the white of
D50, so a pair of tokens keeps its contrast at every hue, to within a few
percent for vivid colours and less for near-greys. In :oklch, the hues
look more even, but the contrast varies more with the hue. The function
worst-contrast says how far it goes.
https://github.com/material-foundation/material-color-utilities/blob/main/typescript/hct/hct.tsColours as people with a colour vision deficiency see them, by the model of Machado, Oliveira and Fernandes.
The model shifts how one kind of cone responds to light: the L cones for a protan deficiency, the M cones for a deutan one, and the S cones for a tritan one. Its severity runs from 0, normal colour vision, to 1. At 1, the protan and deutan simulations are those of dichromats, who lack the cone. The paper treats its tritan simulation as an approximation, and doesn't simulate tritanopia, since the causes of tritan deficiencies aren't well known.
Red-green deficiencies, protan and deutan, affect about 8% of men and 0.4% of women of European descent, while tritan ones are much rarer (the paper, after Sharpe et al.).
The paper derives each matrix from the spectra of a display's primaries, so the matrices apply to linear light, and the namespace applies them in linear sRGB.
Machado, Oliveira and Fernandes, A physiologically-based model for simulation of color vision deficiency, IEEE Transactions on Visualization and Computer Graphics 15(6), 2009, pp. 1291–1298 https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
Colours as people with a colour vision deficiency see them, by the model of Machado, Oliveira and Fernandes. The model shifts how one kind of cone responds to light: the L cones for a protan deficiency, the M cones for a deutan one, and the S cones for a tritan one. Its severity runs from 0, normal colour vision, to 1. At 1, the protan and deutan simulations are those of dichromats, who lack the cone. The paper treats its tritan simulation as an approximation, and doesn't simulate tritanopia, since the causes of tritan deficiencies aren't well known. Red-green deficiencies, protan and deutan, affect about 8% of men and 0.4% of women of European descent, while tritan ones are much rarer (the paper, after Sharpe et al.). The paper derives each matrix from the spectra of a display's primaries, so the matrices apply to linear light, and the namespace applies them in linear sRGB. Machado, Oliveira and Fernandes, A physiologically-based model for simulation of color vision deficiency, IEEE Transactions on Visualization and Computer Graphics 15(6), 2009, pp. 1291–1298 https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |