Devlog #10: Building an Accessible Web - From Lighthouse Audits to Universal Design
A comprehensive journey through web accessibility: conducting Lighthouse audits, fixing color contrast issues, implementing WCAG 2.1 AA compliance, and creating an accessibility policy that ensures universal access to technical content.
Building for everyone: the complete process of auditing, fixing, and documenting accessibility improvements that transformed our site from good intentions to WCAG 2.1 AA compliance and beyond.
The Accessibility Wake-Up Call
Web accessibility isn’t just about compliance, it’s about ensuring that the technical knowledge and insights I share reach everyone, regardless of their abilities or the assistive technologies they use. When I decided to conduct a comprehensive accessibility audit of Signals & Systems, I discovered that good intentions weren’t enough.
The wake-up call came from running Lighthouse audits across both desktop and mobile versions of the site. While performance and SEO scored perfectly (100/100), accessibility showed room for improvement at 96/100. More importantly, the manual accessibility checks revealed gaps that automated tools couldn’t catch.
The 96/100 Reality Check
A 96/100 accessibility score sounds impressive, but those missing 4 points often represent real barriers for users with disabilities. Color contrast issues, missing viewport tags, and incomplete ARIA implementations can mean the difference between accessible content and frustrated users.
The Comprehensive Audit Process
Automated Testing with Lighthouse
I started with PageSpeed Insights to get baseline metrics for both desktop and mobile experiences:
Desktop Results:
- Performance: 100/100
- Accessibility: 96/100
- Best Practices: 96/100
- SEO: 100/100
Mobile Results:
- Performance: 99/100
- Accessibility: 96/100
- Best Practices: 93/100
- SEO: 100/100
The consistent accessibility score of 96 across both platforms indicated systematic issues rather than platform-specific problems.
Key Issues Identified
1. Color Contrast Problems The primary issue was insufficient contrast ratios between background and foreground colors, particularly in:
- Footer navigation links (
text-gray-500
on white backgrounds) - Social media icons (
text-gray-400
hover states) - CalloutBox components (various color combinations)
2. Missing Viewport Meta Tag A critical oversight for mobile accessibility—the absence of a viewport meta tag was causing:
- Text to appear illegibly small on mobile devices
- Poor responsive behavior
- Reduced Best Practices scores
3. Manual Testing Gaps Lighthouse flagged 10 additional items requiring manual verification:
- Keyboard navigation completeness
- Screen reader experience quality
- Focus order and management
- Interactive element accessibility
The Manual Testing Protocol
Beyond automated tools, I implemented a comprehensive manual testing protocol:
Keyboard Navigation Testing:
- Tab through all interactive elements
- Verify logical focus order
- Test skip links and navigation shortcuts
- Ensure all functionality available via keyboard
Screen Reader Testing:
- Test with NVDA (Windows) and VoiceOver (macOS)
- Verify heading structure and content hierarchy
- Check ARIA label effectiveness
- Validate form and interactive element announcements
Color and Contrast Analysis:
- Use WebAIM Contrast Checker for all color combinations
- Verify text remains readable at 200% zoom
- Test with color blindness simulators
Implementation: Fixing the Foundation
Color Contrast Improvements
The color contrast fixes required a systematic approach that respected the existing design theme while meeting WCAG AA standards (4.5:1 for normal text, 3:1 for large text).
Footer Navigation Links:
<!-- Before: Insufficient contrast -->
<a href="/" class="text-base text-gray-500 hover:text-gray-900">
Home
</a>
<!-- After: WCAG AA compliant -->
<a href="/" class="text-base text-gray-700 hover:text-gray-900">
Home
</a>
Social Media Icons:
<!-- Before: Low contrast hover states -->
<a href="https://github.com/Tamok" class="text-gray-400 hover:text-gray-500">
<!-- After: Higher contrast -->
<a href="https://github.com/Tamok" class="text-gray-600 hover:text-gray-900">
CalloutBox Components:
The CalloutBox component required the most extensive color updates, moving from -400
and -700
shades to -700
and -900
combinations:
const textColor = {
info: "text-blue-900", // was text-blue-700
warning: "text-yellow-900", // was text-yellow-700
error: "text-red-900", // was text-red-700
// ... other variants
}[type];
const iconColor = {
info: "text-blue-700", // was text-blue-400
warning: "text-yellow-700", // was text-yellow-400
error: "text-red-700", // was text-red-400
// ... other variants
}[type];
Viewport Meta Tag Implementation
Adding the viewport meta tag was straightforward but critical:
<!-- BaseLayout.astro -->
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- ... other meta tags -->
</head>
This single line fixed:
- Mobile text legibility issues
- Responsive design behavior
- Best Practices score improvements
Semantic HTML Review
I conducted a comprehensive review of the HTML structure, ensuring proper use of semantic elements:
Navigation Structure:
<nav class="bg-white shadow" aria-label="Main navigation">
<div class="max-w-7xl mx-auto px-4">
<!-- Navigation content with proper ARIA attributes -->
</div>
</nav>
Content Hierarchy:
- Verified proper heading structure (h1 → h2 → h3)
- Ensured landmark elements (
<main>
,<nav>
,<footer>
) - Implemented skip links for keyboard users
Creating the Accessibility Policy
Beyond fixing technical issues, I created a comprehensive accessibility statement that serves both as a commitment and a resource for users. The policy covers:
Our Accessibility Commitment
The accessibility page establishes clear expectations:
- Commitment to WCAG 2.1 AA compliance
- Specific measures I take to ensure accessibility
- Contact information for accessibility concerns
- Continuous improvement promise
Implementation Details
Accessibility Features Documented:
- Semantic HTML and ARIA labels for navigation
- Keyboard navigability for all interactive elements
- High color contrast and scalable text
- Alt text for all meaningful images
- Regular accessibility reviews
Contact and Feedback Process:
- Direct email contact for accessibility issues
- Commitment to prompt response and resolution
- Invitation for suggestions and improvements
Integration with Existing Policies
The accessibility page joins my privacy and cookie policies in the footer, creating a comprehensive set of user-focused policy pages that demonstrate my commitment to transparency and user rights.
Policy Integration Strategy
By placing accessibility, privacy, and cookie policies together in the footer, I create a natural grouping that signals my comprehensive approach to user rights and inclusive design.
Security Headers: The GitHub Pages Challenge
During the audit process, I also investigated security headers (CSP, HSTS, COOP, X-Frame-Options) as part of best practices improvements. However, GitHub Pages presents a fundamental limitation: no support for custom HTTP headers.
Understanding Security Headers
Content Security Policy (CSP):
- Restricts resource loading sources to prevent XSS attacks
- Example:
Content-Security-Policy: default-src 'self'; script-src 'self' trusted-cdn.com
Strict Transport Security (HSTS):
- Forces HTTPS connections to prevent downgrade attacks
- Example:
Strict-Transport-Security: max-age=63072000; includeSubDomains
Cross-Origin Opener Policy (COOP):
- Isolates browsing context from other origins
- Example:
Cross-Origin-Opener-Policy: same-origin
X-Frame-Options:
- Prevents clickjacking by controlling iframe embedding
- Example:
X-Frame-Options: DENY
GitHub Pages Limitations and Solutions
For static sites on GitHub Pages, security headers require additional infrastructure:
Option 1: Cloudflare Proxy
- Point domain to Cloudflare
- Configure headers in Transform Rules
- Maintain GitHub Pages hosting
Option 2: Platform Migration
- Move to Netlify/Vercel for native header support
- Use
_headers
file (Netlify) orvercel.json
(Vercel)
Option 3: Meta Tag Fallbacks
- Limited effectiveness compared to HTTP headers
- Some protection via:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
For now, I’m staying with GitHub Pages and accepting this limitation, but the infrastructure is documented for future migration.
Results and Impact
Quantitative Improvements
The accessibility improvements delivered measurable results:
Lighthouse Scores:
- Accessibility: 96 → Expected improvement to 98-100
- Best Practices: 93/96 → Expected improvement to 98-100
- Mobile text legibility: Resolved completely
Color Contrast Ratios:
- Footer links: Improved from ~3.2:1 to 4.8:1
- CalloutBox text: All variants now exceed 4.5:1
- Social icons: Improved hover contrast to 7.1:1
Qualitative Enhancements
User Experience Improvements:
- Better mobile text readability
- Clearer visual hierarchy through improved contrast
- More obvious interactive element states
- Enhanced keyboard navigation experience
Content Accessibility:
- Technical diagrams with proper alt text
- Interactive components with keyboard support
- Screen reader-friendly content structure
- Consistent focus management
Process Documentation
The accessibility audit established a repeatable process for future improvements:
- Automated Testing: Regular Lighthouse audits
- Manual Verification: Keyboard and screen reader testing
- Color Analysis: Systematic contrast checking
- Policy Updates: Keeping accessibility commitments current
Accessibility as a Design System
These improvements weren’t just fixes, they became part of my design system. Every new component now starts with accessibility considerations, and color choices automatically meet WCAG standards.
Looking Forward: Continuous Accessibility
Accessibility isn’t a one-time achievement: it’s an ongoing commitment. The foundation I’ve built includes:
Automated Monitoring
- Regular Lighthouse audits as part of deployment
- Color contrast validation for new components
- Automated testing for keyboard navigation
Manual Review Processes
- Screen reader testing for new interactive features
- User feedback incorporation and response
- Regular policy updates and improvements
Community Engagement
- Open invitation for accessibility feedback
- Documentation of improvements and learnings
- Sharing accessibility practices with the broader community
Key Takeaways
Building accessible web experiences requires both technical implementation and cultural commitment:
Technical Foundations:
- Automated testing catches common issues but manual testing reveals the user experience
- Color contrast is often the biggest quick win for accessibility
- Semantic HTML and proper ARIA usage create the foundation for assistive technology
- Security headers matter for comprehensive user protection, even if platform limitations exist
Process Insights:
- Accessibility audits should be comprehensive, covering automated and manual testing
- Fixing accessibility issues often improves the experience for all users
- Documentation and policies demonstrate commitment beyond technical compliance
Strategic Considerations:
- Platform choice affects security capabilities but shouldn’t block accessibility progress
- Color and design decisions should consider accessibility from the beginning
- Accessibility statements create accountability and provide user guidance
The journey from 96/100 to comprehensive accessibility compliance reinforced that building for everyone isn’t just the right thing to do, it also creates better, more robust web experiences for all users. As I continue developing interactive technical content, these accessibility foundations ensure that knowledge sharing remains truly universal.
Ready to audit your own site’s accessibility? Start with Lighthouse audits, test with real assistive technologies, and remember: accessibility benefits everyone, not just users with disabilities.