rustyle_css/a11y/
contrast.rs1use crate::css::Color;
6
7fn relative_luminance(color: &Color) -> f64 {
9 match color {
12 Color::Rgb(r, g, b) => {
13 let r = *r as f64 / 255.0;
14 let g = *g as f64 / 255.0;
15 let b = *b as f64 / 255.0;
16
17 let r = if r <= 0.03928 {
18 r / 12.92
19 } else {
20 ((r + 0.055) / 1.055).powf(2.4)
21 };
22 let g = if g <= 0.03928 {
23 g / 12.92
24 } else {
25 ((g + 0.055) / 1.055).powf(2.4)
26 };
27 let b = if b <= 0.03928 {
28 b / 12.92
29 } else {
30 ((b + 0.055) / 1.055).powf(2.4)
31 };
32
33 0.2126 * r + 0.7152 * g + 0.0722 * b
34 }
35 _ => 0.5, }
37}
38
39pub fn contrast_ratio(foreground: &Color, background: &Color) -> f64 {
41 let l1 = relative_luminance(foreground);
42 let l2 = relative_luminance(background);
43
44 let lighter = l1.max(l2);
45 let darker = l1.min(l2);
46
47 (lighter + 0.05) / (darker + 0.05)
48}
49
50pub fn meets_wcag_aa(foreground: &Color, background: &Color, large_text: bool) -> bool {
52 let ratio = contrast_ratio(foreground, background);
53 if large_text {
54 ratio >= 3.0
55 } else {
56 ratio >= 4.5
57 }
58}
59
60pub fn meets_wcag_aaa(foreground: &Color, background: &Color, large_text: bool) -> bool {
62 let ratio = contrast_ratio(foreground, background);
63 if large_text {
64 ratio >= 4.5
65 } else {
66 ratio >= 7.0
67 }
68}
69
70pub fn adjust_for_contrast(foreground: &mut Color, background: &Color, target_ratio: f64) {
72 let current_ratio = contrast_ratio(foreground, background);
75 if current_ratio < target_ratio {
76 }
78}