Module: Abachrome::ColorMixins::Wcag

Defined in:
lib/abachrome/color_mixins/wcag.rb

Instance Method Summary collapse

Instance Method Details

#contrast_ratio(other) ⇒ AbcDecimal

Calculates the contrast ratio between this color and another color. The contrast ratio is calculated according to WCAG: (L1 + 0.05) / (L2 + 0.05) where L1 is the relative luminance of the lighter color and L2 is the relative luminance of the darker color.

Parameters:

Returns:

  • (AbcDecimal)

    The contrast ratio, ranging from 1:1 (no contrast) to 21:1 (maximum contrast)



57
58
59
60
61
62
63
64
65
# File 'lib/abachrome/color_mixins/wcag.rb', line 57

def contrast_ratio(other)
  l1 = relative_luminance
  l2 = other.relative_luminance

  # Ensure L1 is the lighter color
  l1, l2 = l2, l1 if l1 < l2

  (l1 + AbcDecimal("0.05")) / (l2 + AbcDecimal("0.05"))
end

#meets_wcag_aa?(other, large_text: false) ⇒ Boolean

Checks if the contrast ratio with another color meets WCAG 2.0 Level AA standards. AA requirements:

  • Normal text (< 18pt or < 14pt bold): minimum 4.5:1 contrast ratio
  • Large text (≥ 18pt or ≥ 14pt bold): minimum 3:1 contrast ratio

Parameters:

  • other (Abachrome::Color)

    The color to compare against

  • large_text (Boolean) (defaults to: false)

    Whether the text is considered large (default: false)

Returns:

  • (Boolean)

    true if the contrast meets AA standards



75
76
77
78
79
# File 'lib/abachrome/color_mixins/wcag.rb', line 75

def meets_wcag_aa?(other, large_text: false)
  ratio = contrast_ratio(other)
  minimum = large_text ? AbcDecimal("3.0") : AbcDecimal("4.5")
  ratio >= minimum
end

#meets_wcag_aaa?(other, large_text: false) ⇒ Boolean

Checks if the contrast ratio with another color meets WCAG 2.0 Level AAA standards. AAA requirements:

  • Normal text (< 18pt or < 14pt bold): minimum 7:1 contrast ratio
  • Large text (≥ 18pt or ≥ 14pt bold): minimum 4.5:1 contrast ratio

Parameters:

  • other (Abachrome::Color)

    The color to compare against

  • large_text (Boolean) (defaults to: false)

    Whether the text is considered large (default: false)

Returns:

  • (Boolean)

    true if the contrast meets AAA standards



89
90
91
92
93
# File 'lib/abachrome/color_mixins/wcag.rb', line 89

def meets_wcag_aaa?(other, large_text: false)
  ratio = contrast_ratio(other)
  minimum = large_text ? AbcDecimal("4.5") : AbcDecimal("7.0")
  ratio >= minimum
end

#meets_wcag_non_text?(other) ⇒ Boolean

Checks if the contrast ratio with another color meets WCAG 2.1 non-text contrast requirements. Non-text contrast applies to:

  • Graphical objects (icons, graphs, infographics)
  • User interface components (buttons, form inputs, focus indicators) Requirement: minimum 3:1 contrast ratio

Parameters:

Returns:

  • (Boolean)

    true if the contrast meets the 3:1 minimum for non-text content



103
104
105
106
# File 'lib/abachrome/color_mixins/wcag.rb', line 103

def meets_wcag_non_text?(other)
  ratio = contrast_ratio(other)
  ratio >= AbcDecimal("3.0")
end

#relative_luminanceAbcDecimal

Calculates the relative luminance of the color according to WCAG specifications. Uses the formula: Y = 0.2126R + 0.7152G + 0.0722B where R, G, B are linearized sRGB values.

The linearization follows the sRGB specification:

  • For values <= 0.03928: linear_value = value / 12.92
  • For values > 0.03928: linear_value = ((value + 0.055) / 1.055) ^ 2.4

Returns:

  • (AbcDecimal)

    The relative luminance value between 0.0 (darkest) and 1.0 (lightest)



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/abachrome/color_mixins/wcag.rb', line 34

def relative_luminance
  rgb = to_srgb
  r, g, b = rgb.coordinates

  # Linearize sRGB values
  r_linear = linearize_srgb_component(r)
  g_linear = linearize_srgb_component(g)
  b_linear = linearize_srgb_component(b)

  # Apply WCAG luminance coefficients (Rec. 709)
  AbcDecimal("0.2126") * r_linear +
    AbcDecimal("0.7152") * g_linear +
    AbcDecimal("0.0722") * b_linear
end