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.