Color.Contrast
(Color v0.4.0)
Copy Markdown
Contrast and luminance computations.
relative_luminance/1— theYcomponent of an sRGB color as defined by WCAG 2.x (applies the sRGB inverse companding then takes0.2126·R + 0.7152·G + 0.0722·B).wcag_ratio/2— WCAG 2.x contrast ratio,(L1 + 0.05) / (L2 + 0.05)whereL1 ≥ L2. Result range[1.0, 21.0].wcag_level/2— classifies a pair as:aaa,:aaa_large,:aa,:aa_large, or:failfor the common normal-text / large-text thresholds.apca/2— the Accessible Perceptual Contrast Algorithm (APCA W3 0.1.9), the successor to WCAG 2 proposed for CSS Color 5. Returns a signedL_cvalue roughly in[-108, 106].pick_contrasting/3— given a background and two candidate foregrounds, pick the one with the higher contrast against the background.
All inputs may be anything accepted by Color.new/1.
Summary
Functions
Returns the APCA L_c contrast value between a text colour and a
background colour.
Picks the candidate that gives the higher WCAG contrast against the background.
Returns the WCAG 2.x relative luminance of a color — the Y
component of its linear sRGB, on the [0, 1] scale.
Classifies a WCAG contrast ratio into the accessibility grade it meets for normal and large text.
Returns the WCAG 2.x contrast ratio between two colors.
Functions
@spec apca(Color.input(), Color.input()) :: float()
Returns the APCA L_c contrast value between a text colour and a
background colour.
APCA is directional: swapping the arguments can change the magnitude and sign of the result. Positive values mean the text is darker than the background (normal polarity); negative values mean lighter text on a darker background (reverse polarity).
Values are roughly in the range [-108, 106]. The rough thresholds
suggested by the APCA spec are:
|Lc| ≥ 90— body text under the WCAG 3 "fluent" rating.|Lc| ≥ 75— body text, content.|Lc| ≥ 60— content, large headlines.|Lc| ≥ 45— large / bold text.|Lc| ≥ 30— non-text ornamental.
Reference: https://github.com/Myndex/apca-w3 (APCA-W3 0.1.9).
Arguments
textis the foreground colour — anything accepted byColor.new/1.backgroundis the background colour.
Returns
- A signed float.
Examples
iex> Float.round(Color.Contrast.apca("black", "white"), 1)
106.0
iex> Float.round(Color.Contrast.apca("white", "black"), 1)
-107.9
@spec pick_contrasting(Color.input(), [Color.input()]) :: {:ok, Color.SRGB.t()} | {:error, Exception.t()}
Picks the candidate that gives the higher WCAG contrast against the background.
Arguments
backgroundis any color accepted byColor.new/1.candidatesis a list of colors accepted byColor.new/1. Defaults to["white", "black"].
Returns
{:ok, color_struct}wherecolor_structis the chosen candidate as aColor.SRGBstruct.
Examples
iex> {:ok, chosen} = Color.Contrast.pick_contrasting("white")
iex> Color.SRGB.to_hex(chosen)
"#000000"
iex> {:ok, chosen} = Color.Contrast.pick_contrasting("#333")
iex> Color.SRGB.to_hex(chosen)
"#ffffff"
iex> {:ok, chosen} = Color.Contrast.pick_contrasting("red", ["yellow", "darkblue"])
iex> Color.SRGB.to_hex(chosen)
"#00008b"
@spec relative_luminance(Color.input()) :: float()
Returns the WCAG 2.x relative luminance of a color — the Y
component of its linear sRGB, on the [0, 1] scale.
Arguments
coloris anything accepted byColor.new/1.
Returns
- A float in
[0, 1].
Examples
iex> Color.Contrast.relative_luminance("white")
1.0
iex> Color.Contrast.relative_luminance("black")
0.0
iex> Float.round(Color.Contrast.relative_luminance("red"), 4)
0.2126
@spec wcag_level(Color.input(), Color.input()) :: :aaa | :aaa_large | :aa_large | :fail
Classifies a WCAG contrast ratio into the accessibility grade it meets for normal and large text.
The thresholds are:
AAA —
7.0normal text,4.5large text.AA —
4.5normal text,3.0large text.
Arguments
ais any color accepted byColor.new/1.bis any color accepted byColor.new/1.
Returns
- One of
:aaa,:aaa_large,:aa,:aa_large,:fail.
Examples
iex> Color.Contrast.wcag_level("black", "white")
:aaa
iex> Color.Contrast.wcag_level("#777", "white")
:aa_large
@spec wcag_ratio(Color.input(), Color.input()) :: float()
Returns the WCAG 2.x contrast ratio between two colors.
Arguments
ais any color accepted byColor.new/1.bis any color accepted byColor.new/1.
Returns
- A float in
[1.0, 21.0].1.0means no contrast;21.0is the maximum (black on white or white on black).
Examples
iex> Float.round(Color.Contrast.wcag_ratio("white", "black"), 2)
21.0
iex> Float.round(Color.Contrast.wcag_ratio("#777", "white"), 2)
4.48