WCAG 2.0 Inclusive Code
When you're building software for a government audience, accessibility isn't optional — it's expected. But even outside the public sector, accessibility is just good engineering. It means building products that everyone can use, regardless of ability, context, or device.
I learned that the hard way — and I'm better for it.
The Wake-Up Call
It started when I was working on an EduTech platform, developing readers on a digital school platform (think Canvas or moodle). The audience of the app, as you can guess, are students and teachers. While the app is technically sound, we had a long list of technical debts on accessibility that have been sidelined for a while.
Then came the audit.
A review flagged the app for failing multiple WCAG 2.0 Level AA requirements. No proper keyboard navigation. Low-contrast buttons. Forms without labels. It wasn’t hostile to users with disabilities — it just didn’t include them.
Time to fix that.
Understanding WCAG 2.0 (Without the Bureaucratic Headache)
Before jumping into code, I needed to understand the Web Content Accessibility Guidelines (WCAG). They're organized under four main principles, known as POUR:
- Perceivable – Information must be available to all the senses.
- Operable – Navigation and interface must work with keyboard and assistive tech.
- Understandable – Content and UI must be clear and consistent.
- Robust – Code must be compatible with current and future tech.
For WCAG 2.0 AA (the standard in most regulated environments), that means meeting 38 criteria. Not optional. Not suggestions. Requirements.
Breaking It Down: The Fix List
Here’s some items that me and my team tackled, one item at a time:
✅ Keyboard Navigation
- Ensured all interactive elements were reachable via
Tab
andShift+Tab
. - Managed focus order with semantic HTML and proper element hierarchy.
- Removed
div
-based "buttons" and replaced them with actual<button>
elements.
✅ Color Contrast
- Used WebAIM’s Contrast Checker to test backgrounds and text.
- Updated Tailwind CSS tokens and themes to ensure a minimum 4.5:1 contrast ratio.
✅ Form Labels & ARIA
- Added explicit
<label>
tags to every form input. - Used
aria-describedby
andaria-labelledby
for dynamic components (like search filters or modals). - Provided accessible error messages linked via
aria-live
.
✅ Alt Text and Media
- Audited every image and icon.
- Used meaningful
alt
text (not just "icon" or "image"). - Skipped decorative icons using
aria-hidden="true"
.
✅ Headings and Landmarks
- Structured pages using
<h1>
through<h4>
components properly (no skipping levels). - Wrapped main sections with landmarks:
<main>
,<nav>
,<header>
,<footer>
. - Ensured screen reader users could skip to content quickly.
Tools That Helped
- axe DevTools – Chrome extension that caught most common WCAG violations.
- NVDA (Windows screen reader) – Tested screen reader flows without relying on assumptions.
- Lighthouse – Google's accessibility audit in Chrome DevTools.
- eslint-plugin-jsx-a11y – Static code checks for accessibility in React components.
I'm aware that there are many more aspects. Internationalization, cognitive accessibility, focus management, and many more.
A Developer's Perspective: What Changed
Accessibility isn’t just a checklist. It’s a mindset.
It’s about intentional design — making sure what you build serves every user. It’s also about resilience. Good accessible code is more semantic, maintainable, and robust by default.
And bonus: many of the fixes improved usability for everyone, not just people with disabilities.
Takeaways for future projects
- Don’t treat accessibility as a last-minute patch.
- Learn the HTML spec — it’s more powerful than most frontend libraries let on.
- Talk to users. Accessibility isn’t just technical; it’s empathetic.
- Use tools early and often. Linting and testing save you from rework.
Final Thoughts
Reaching WCAG 2.0 compliance wasn’t a one-time fix. It was a shift in how I approach development — thinking upstream in architecture, and building downstream with empathy. Today, accessibility is baked into my workflow, not bolted on.
The web feels better this way.