about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorelioat <{ID}+{username}@users.noreply.github.com>2025-02-10 15:29:56 -0500
committerelioat <{ID}+{username}@users.noreply.github.com>2025-02-10 15:33:37 -0500
commit191c64514ee6d740d2cc8d35f955ff721f83c128 (patch)
tree4901733034b39cc2caadeac5df470689d6102fe5
parent6433ceb81940ab9b567c2c6868ed9ba0c57747ad (diff)
downloadtour-191c64514ee6d740d2cc8d35f955ff721f83c128.tar.gz
*
-rw-r--r--html/color-contrast-checker/index.html113
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>