diff options
author | elioat <{ID}+{username}@users.noreply.github.com> | 2025-02-10 15:29:56 -0500 |
---|---|---|
committer | elioat <{ID}+{username}@users.noreply.github.com> | 2025-02-10 15:33:37 -0500 |
commit | 191c64514ee6d740d2cc8d35f955ff721f83c128 (patch) | |
tree | 4901733034b39cc2caadeac5df470689d6102fe5 | |
parent | 6433ceb81940ab9b567c2c6868ed9ba0c57747ad (diff) | |
download | tour-191c64514ee6d740d2cc8d35f955ff721f83c128.tar.gz |
*
-rw-r--r-- | html/color-contrast-checker/index.html | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/html/color-contrast-checker/index.html b/html/color-contrast-checker/index.html new file mode 100644 index 0000000..30a1d66 --- /dev/null +++ b/html/color-contrast-checker/index.html @@ -0,0 +1,113 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Color Contrast Checker</title> + <style> + body { font-family: Arial, sans-serif; padding: 20px; } + .color-input { margin-bottom: 10px; width: 100%; height: 100px; } + .color-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; } + .color-box { padding: 10px; text-align: center; border: 1px solid #ccc; } + .hidden { display: none; } + .form-controls { display: flex; justify-content: space-between; align-items: center; } + .checkbox-controls { display: flex; gap: 20px; } + </style> +</head> +<body> + <header> + <h1>What color combinations are accessible?</h1> + </header> + <main> + <form id="colorForm" onsubmit="event.preventDefault(); updateColors();"> + <label for="colors">Enter hex color codes (comma or newline-separated):</label> + <textarea id="colors" class="color-input" required></textarea> + <div class="form-controls"> + <button type="submit">Check Contrast</button> + <div class="checkbox-controls"> + <label><input type="checkbox" id="toggleFails" onchange="updateVisibility()"> Hide failing pairs</label> + <label><input type="checkbox" id="sortContrast" onchange="updateColors()"> Sort by contrast</label> + </div> + </div> + </form> + <br> + <br> + <section id="results" class="color-grid" aria-live="polite"></section> + </main> + <footer> + <p>Color Contrast Checker - A tool to help you find accessible color combinations.</p> + </footer> + + <script> + function getContrastRatio(c1, c2) { + function luminance(r, g, b) { + let a = [r, g, b].map(v => { + v /= 255; + return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4; + }); + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; + } + let rgb1 = c1.match(/\w\w/g).map(x => parseInt(x, 16)); + let rgb2 = c2.match(/\w\w/g).map(x => parseInt(x, 16)); + let lum1 = luminance(...rgb1); + let lum2 = luminance(...rgb2); + return (Math.max(lum1, lum2) + 0.05) / (Math.min(lum1, lum2) + 0.05); + } + + function getWCAGLevel(contrast) { + if (contrast >= 7) return "AAA"; + if (contrast >= 4.5) return "AA"; + return "Fail"; + } + + function createColorBox(color1, color2, contrast, level, accessible, showGlow) { + const classes = ["color-box"]; + if (!accessible) classes.push("failing"); + if (level === "AAA" && showGlow) classes.push("glowing-border"); + + return ` + <div class="${classes.join(' ')}" style="background: ${color1}; color: ${color2};"> + ${color1} on ${color2}<br> + Ratio: ${contrast} ${accessible ? "✅" : "❌"}<br> + WCAG: ${level} + </div> + `; + } + + function updateColors() { + const input = document.getElementById("colors").value; + const colors = input.split(/[\n,]+/).map(c => c.trim()).filter(c => c); + const results = document.getElementById("results"); + + const colorCombinations = colors.flatMap((color1, i) => + colors.slice(i + 1).map(color2 => { + const contrast = getContrastRatio(color1, color2).toFixed(2); + const level = getWCAGLevel(contrast); + const accessible = level !== "Fail"; + return { color1, color2, contrast, level, accessible }; + }) + ); + + const sortByContrast = document.getElementById("sortContrast").checked; + if (sortByContrast) { + colorCombinations.sort((a, b) => b.contrast - a.contrast); + } + + const colorBoxes = colorCombinations.map(({ color1, color2, contrast, level, accessible }) => { + return createColorBox(color1, color2, contrast, level, accessible, false); + }); + + results.innerHTML = colorBoxes.join(''); + updateVisibility(); + } + + function updateVisibility() { + let hideFails = document.getElementById("toggleFails").checked; + + document.querySelectorAll(".failing").forEach(box => { + box.style.display = hideFails ? "none" : "block"; + }); + } + </script> +</body> +</html> |