6.4 KiB
Contrast Detection Fixes
Problems
The contrast checking tool had three issues that caused false positives and incorrect reporting:
Issue 1: White-on-White False Positives
Example: Vision Leadership sponsor page (https://visionleadership.org/sponsor-opportunities/)
- Reported: White text
rgb(255, 255, 255)on white backgroundrgb(255, 255, 255)= 1:1 ratio (FAIL) - Reality: White text on gradient background
linear-gradient(rgb(12, 90, 201) 0%, rgb(0, 0, 0) 100%) - Actual Contrast: 6.32:1 to 21:1 (PASS)
Root Cause: The gradient was on a parent container (.et_pb_section), not directly on the text elements. The tool only checked the element itself for gradients, not parent elements.
Issue 2: Gradient Applied to Wrong Elements
After the initial fix, the tool became too aggressive:
- Reported: 54 elements with blue background
rgb(12, 90, 201)(from gradient) - Reality: Those elements were on light gray
rgb(252, 252, 252)background - Root Cause: Gradient detection walked up the tree but didn't stop when it encountered solid backgrounds
Issue 3: Wrong Text Color for Elements with Child Spans
The tool used parent element colors instead of actual visible text colors:
- Example:
<a>element withcolor: bluecontaining<span>withcolor: rgb(12, 90, 201) - Reported: Used the
<a>'s color - Reality: The visible text uses the
<span>'s color - Root Cause: Tool only checked the matched element's color, not child elements that contain the actual text
Solutions
Modified the contrast detection logic in daemon/daemon.go to:
- Walk up the DOM tree to find gradient backgrounds on parent elements
- Stop at solid backgrounds - if a solid background color is found before a gradient, use the solid color
- Only apply gradients when no solid background exists between the element and the gradient
- Check child elements for text color - if an element has visible child elements with text, use the first child's color instead of the parent's color
Code Changes
1. Enhanced analyzeGradientContrast Function (Lines 9152-9220)
Before: Only checked the element itself for gradients
After:
- Walks up the DOM tree looking for gradients
- Checks for solid backgrounds at each level
- Returns
nullif a solid background is found (gradient doesn't apply) - Only returns gradient info if no solid background blocks it
function analyzeGradientContrast(element, textColor) {
let current = element;
while (current && current !== document.documentElement.parentElement) {
const style = window.getComputedStyle(current);
// Check for solid background first - if found, gradient doesn't apply
const bgColor = style.backgroundColor;
if (!isTransparent(bgColor)) {
return null; // Solid background found
}
// Check for gradient
const bgImage = style.backgroundImage;
if (bgImage && bgImage.includes('gradient')) {
// Extract and analyze gradient colors...
return gradientInfo;
}
current = current.parentElement;
}
return null;
}
2. Updated Background Detection Logic (Lines 9305-9340)
Before: Always checked for gradients, even when solid backgrounds were found
After:
- Tier 1: Check for solid backgrounds via DOM tree walking
- Tier 2: Check for solid backgrounds via stacking context
- Tier 3: Only check for gradients if no solid background found
- Fallback: Use white if nothing found
// Tier 1: DOM tree walking for solid colors
bgColor = getEffectiveBackgroundDOMTree(element);
// Tier 2: Stacking context analysis (if Tier 1 failed)
if (!bgColor) {
bgColor = getBackgroundFromStackingContext(element);
}
// Tier 3: Check for gradients (only if no solid color found)
if (!bgColor) {
gradientInfo = analyzeGradientContrast(element, fgColor);
if (gradientInfo) {
bgColor = gradientInfo.colors[0];
}
}
// Fallback to white
if (!bgColor) {
bgColor = 'rgb(255, 255, 255)';
}
Testing
After deploying the fix, test on:
- Vision Leadership sponsor page - Should correctly detect gradient and report passing contrast
- Elements with solid backgrounds - Should not incorrectly apply gradients from parent containers
- Nested backgrounds - Should use the closest background (solid or gradient)
Expected Results
Vision Leadership Hero Section
- H1 "Sponsorship Opportunities That Work For You"
- Detection method:
gradient-analysis - Gradient colors:
rgb(12, 90, 201)torgb(0, 0, 0) - Worst contrast: 6.32:1 (PASS AA for large text)
- Best contrast: 21:1 (PASS AAA)
- Detection method:
Elements with Solid Backgrounds
- Text on light gray
rgb(252, 252, 252)- Detection method:
dom-treeorstacking-context - Should NOT use gradient from parent
- Should calculate contrast against actual gray background
- Detection method:
Deployment
- Build the daemon:
make daemon - Build the MCP server:
make mcp - Restart the cremote daemon (deployment-specific process)
- Restart the MCP server or Augment extension to pick up changes
3. Enhanced Text Color Detection (Lines 9257-9322)
Before: Always used the matched element's text color
After:
- Checks if the element has visible child elements with text
- If child elements exist, uses the first child's color
- This ensures we get the actual visible text color, not the parent container's color
// Get the actual text-bearing element for accurate color detection
let textElement = element;
let textStyle = style;
// Check if element has child elements (not just text nodes)
const childElements = Array.from(element.children).filter(child => {
const childText = child.textContent.trim();
if (!childText) return false;
const childStyle = window.getComputedStyle(child);
return childStyle.display !== 'none' && childStyle.visibility !== 'hidden';
});
// If there are visible child elements with text, use the first one's color
if (childElements.length > 0) {
textElement = childElements[0];
textStyle = window.getComputedStyle(textElement);
}
const fgColor = textStyle.color;
Files Modified
daemon/daemon.go- Lines 9152-9220 (gradient analysis function)daemon/daemon.go- Lines 9305-9340 (background detection logic)daemon/daemon.go- Lines 9257-9322 (text color detection enhancement)