Capstone: Auditing and Fixing an Inaccessible Page

Web Accessibility — Capstone: Auditing and Fixing an Inaccessible Page
Web Accessibility (a11y)
Chapter 9 · Capstone: Auditing and Fixing an Inaccessible Page

🏁 Capstone: Auditing and Fixing an Inaccessible Page

Every previous chapter built one piece in isolation. This capstone walks one deliberately inaccessible example page through a real audit — automated scan, semantic HTML, ARIA, keyboard, forms, visual design, screen-reader specifics, and custom components — using every technique from the course, then confirms it with a real screen reader.

The Starting Page

An e-commerce product page with a realistic pile of problems: div-based nav "buttons," a conflicting <a role="button">, no skip link, a modal that doesn't trap or restore focus, placeholder-only form fields, color-only stock status, user-scalable=no, an unthrottled carousel ignoring prefers-reduced-motion, repeated "Read more" links with no context, misused aria-live="assertive", and a custom tabs widget with ARIA roles but no arrow-key support.

1️⃣ Automated Scan First

Run axe/Lighthouse (Chapter 1) to catch the mechanically-detectable ~30–40%: missing labels, low contrast, missing alt text. This is the starting point, not the finish line.

2️⃣ Fix Semantic HTML & ARIA

<!-- Before --> <div onclick="goToCart()">Cart</div> <a href="/wishlist" role="button">Wishlist</a> <!-- After — Ch.2 native elements, Ch.3 no conflicting/redundant ARIA --> <button onclick="goToCart()">Cart</button> <a href="/wishlist">Wishlist</a>

3️⃣ Fix Keyboard Navigation

Add a skip link and :focus-visible styling (never outline: none alone), and fix the modal to move focus in, trap it, and restore it on close — Chapter 4's full three-step checklist, none of which was implemented before.

4️⃣ Fix Forms

<!-- Before --> <input placeholder="Promo code"> <!-- After — Ch.5 real label + accessible error --> <label for="promo">Promo code</label> <input id="promo" aria-describedby="promo-error"> <span id="promo-error">Code expired</span>

5️⃣ Fix Visual Design

Raise low-contrast text to meet Chapter 6's 4.5:1 threshold, add a text label alongside the color-only "in stock/out of stock" indicator, remove user-scalable=no, and add a prefers-reduced-motion override for the carousel.

6️⃣ Fix Screen-Reader-Specific Issues

Add visually-hidden context to every repeated "Read more" link (Chapter 7), and downgrade the routine "item added to cart" announcement from aria-live="assertive" to "polite".

7️⃣ Fix Custom Components

Add roving-tabindex arrow-key navigation to the product-details tabs widget (Chapter 8) — the ARIA roles were already present, but arrow-key support was missing entirely.

8️⃣ Manual Re-Test With a Real Screen Reader

Confirm every fix actually works by testing with VoiceOver or NVDA (Chapter 7) — not just re-running the automated scan, which would still miss reading order and interaction-flow issues no scanner can catch.

The Reusable Methodology

Automated scan → semantic/ARIA → keyboard → forms → visual → screen-reader specifics → components → manual re-test. Not specific to this one page — a repeatable process for auditing any real page.

What Changed the Experience

The page went from unusable for keyboard/screen-reader users to one where every control is reachable, operable, correctly announced, and never leaves someone stuck or lost.

💻 Coding Challenges

Challenge 1: Fix the Carousel's Reduced-Motion Gap

The page's product-image carousel auto-rotates every 4 seconds with a sliding animation and completely ignores prefers-reduced-motion. Write the CSS fix, citing which chapter's principle it applies.

Goal: Practice applying a specific earlier-chapter fix within this capstone's broader audit.

→ Solution

Challenge 2: Explain Why Step 2 Should Happen Before Step 3

Explain why converting div-based buttons to real <button> elements (Step 2) should happen before fixing the skip link and focus trap (Step 3), rather than in the reverse order.

Goal: Practice reasoning about why this methodology's step order isn't arbitrary.

→ Solution

Challenge 3: Apply the Methodology to a New Page

A completely different page — a SaaS dashboard with a data table, a settings form, and a notification bell icon — has accessibility problems. Walk through this chapter's eight-step methodology at a high level for this page, without writing code.

Goal: Practice applying the reusable audit process to a page this course never specifically covered.

→ Solution

⚠️ Gotcha: Trusting a Clean Automated Re-Scan as "Done"

After applying every fix, it's tempting to re-run axe/Lighthouse, see zero flagged issues, and call the audit complete — exactly the mistake Chapter 1 warned against from the very start of this course. Fixes can also interact: converting div-buttons to real <button> elements in Step 2 changes the page's actual tab order and count, which can shift where a skip link should land or where a focus trap's boundaries actually are — issues an automated scanner has no way to catch, since it doesn't understand what "makes sense" during real, continuous keyboard or screen reader use. Re-test manually after each round of fixes, not just once at the end, and never mistake an automated-clean report for a genuinely accessible page.

🎓 Course Complete

This closes out Web Accessibility (a11y) — from why accessibility matters and the POUR principles, through semantic HTML, ARIA, keyboard navigation, forms, color and contrast, screen readers, accessible components, and finally this capstone auditing a real page end to end.