Demo store, fictional No client, no real audit. Built to show how we work.

Case study (demo): 30 Shopify theme accessibility issues, fixed

Kettlecrest Outfitters is a fictional storefront we built to show how we work. We seeded it with defect types common on real Shopify stores, wrote a 30-issue mock review against WCAG 2.2 Level AA, and fixed every issue on a duplicate theme.

Open the before store or the after store. Download the case study (PDF, 317 KB).

Store
Kettlecrest Outfitters (fictional)
Theme
“Basecamp” v2.3, a fictional Shopify-style theme
Review
Mock review, 30 issues: 7 critical, 15 high, 7 medium, 1 low
Target
WCAG 2.2 Level AA
Templates
Home, collection, product, in 8 page states
Widths
Desktop 1280 px, mobile 390 px
Where
On a duplicate. The original was never changed.

Results

  • axe-core rules violated

    Before: 12After: 0

    659 affected elements before, 0 after, over 16 scans

  • Scripted retest per issue

    Before: 0/30After: 30/30

    One keyboard and accessibility-tree check per issue

  • Keyboard-only shopping task

    Before: FailAfter: Pass

    11 of 12 steps failed before; 12 of 12 pass after

  • Lighthouse accessibility

    Before: 43–52After: 100

    Home, collection and product, desktop

The before store is a deliberately dense mix of common defect types; real stores usually show fewer automated failures but the same manual-only ones.

What the review found

Axe flagged 13 of the 30 issues. The other 17 needed keyboard and screen reader testing.

By category

  • Keyboard and focus6
  • Forms and inputs4
  • Dialogs and overlays3
  • Names, roles, values3
  • Images and alt text3
  • Visual design and contrast3
  • Page structure3
  • Status and errors2
  • Third-party apps2
  • Motion and timing1

We pressed Tab through the product page

Demo store, fictional
Show the product page
Demo product page before fixes, showing color swatches, size buttons, quantity and Add to cart.

Focus jumps past color and size.

Where focus landed

  1. 12 Link “128 reviews”
  2. 13 Link “click here”, after jumping past color and size
  3. 14 Quantity field, with no label
  4. 15 Add to cart, which then fails: no size selected
Demo product page after fixes, with a Quantity label, a checked color swatch and named controls.

Every control is a tab stop.

Where focus landed

  1. 18 Link “128 reviews”
  2. 19 Color group, radio “Forest”, checked
  3. 20 Size group, radio “S”
  4. 21 Link “See the Ridgeline size guide”
  5. 22 Button “Decrease quantity”
  6. 23 Field “Quantity”
  7. 24 Button “Increase quantity”
  8. 25 Button “Add to cart”
  9. 26 Details disclosure

Recorded with Playwright at 1280 × 900: Tab pressed from the top of the page, newsletter popup dismissed first on both versions.

What we changed

Ten groups of fixes, each mapped to its issue IDs in the change log.

  • Color and size pickers

    Issue IDs: KC-009KC-018

    Clickable <div>s rebuilt as native radio groups; checked state shown with ring + checkmark; sold-out size disabled and named.

  • Popup, cart drawer and search

    Issue IDs: KC-013KC-014KC-022

    Native modal <dialog>s: focus moves in, Escape closes, real close buttons, focus returns to the opener.

  • Add-to-cart feedback and errors

    Issue IDs: KC-015KC-025

    Focus lands on a visible “Added to your cart…” confirmation (also the dialog description); errors use role="alert" and are linked to fields.

  • Visible focus

    Issue IDs: KC-007KC-008KC-011

    Global outline reset removed; two-tone :focus-visible ring; no more invisible focus on hidden slides or quick-add buttons.

  • Mega menu and carousel

    Issue IDs: KC-010KC-012

    APG disclosure menu (button, aria-expanded, Escape); APG carousel with visible pause and no autoplay under reduced motion.

  • Names for controls and links

    Issue IDs: KC-002KC-008KC-028

    Icon-only buttons and links named (“Search”, “Cart, 2 items”, “Quick add … to cart”); “click here” links rewritten.

  • Forms

    Issue IDs: KC-017KC-020KC-024KC-026KC-029

    Visible labels instead of placeholders, autocomplete, linked and announced errors, native filter checkboxes, labelled sort and quantity.

  • Page structure

    Issue IDs: KC-001KC-004KC-019KC-023

    lang, zoom re-enabled, skip link, landmarks, one h1 per page and ordered headings, with the same visual design.

  • Images and ratings

    Issue IDs: KC-003KC-021KC-030

    Real alt text (empty where decorative); gallery alt follows color and view; ratings read “Rated 4.6 out of 5”.

  • Contrast

    Issue IDs: KC-005KC-006KC-027

    Theme color tokens adjusted to 4.5:1, scrim behind hero text, review-app colors overridden.

Two of the diffs

Straight from the demo’s fix.diff. On a real Shopify theme, the same changes land in the files named in brackets in the change log.

theme.css → assets/base.cssKC-007
  *, *::before, *::after { box-sizing: border-box; }- *:focus { outline: none; }- a:focus, button:focus, input:focus, select:focus, textarea:focus { outline: none; }+ /* KC-007: visible, two-tone focus indicator */+ :focus-visible {+   outline: 3px solid var(--focus);+   outline-offset: 2px;+   box-shadow: 0 0 0 5px #fff;+ }
KC-007, Critical, SC 2.4.7. The focus indicator had been removed sitewide.
cart drawer → snippets/cart-drawer.liquidKC-022
- <div class="cart-overlay"></div>- <div class="cart-drawer" data-qa="cart-drawer">+ <dialog class="cart-drawer" id="cart-drawer" aria-labelledby="cart-title">    <div class="cart-head">-     <div class="cart-title">Your cart</div>-     <span class="cart-close"><svg …></span>+     <h2 class="cart-title" id="cart-title" tabindex="-1">Your cart</h2>+     <button type="button" class="cart-close"><svg aria-hidden="true" …>+       <span class="visually-hidden">Close cart</span></button>+   <p class="visually-hidden" role="status" id="cart-live"></p>
KC-022, Critical, SC 2.1.1, 2.4.3, 4.1.2. The drawer becomes a named modal dialog with a real close button.

The keyboard-only shopping task

Dismiss the first-visit popup, open the Ridgeline 40L Pack, choose Slate and size L, add to cart, check the cart drawer takes focus and announces the add, close it with Escape, focus returns.

Keyboard task steps, before and after fixes
StepBeforeAfter
Popup moves keyboard focus into itselfFailPass
Tab keeps focus inside the popupFailPass
Escape closes the popupFailPass
Reach the product link with TabPass, focus not visiblePass
Choose color “Slate” with the keyboardFailPass
Choose size “L” with the keyboardFailPass
Add to cart with EnterFailPass
Cart drawer opens and receives focusFailPass
The add is exposed to screen readersFailPass
Escape closes the cart drawerFailPass
Focus returns to “Add to cart”FailPass
Visible focus on every control usedFailPass

What a screen reader heard on Add to cart

Before. Press Enter on “Add to cart” (size picked with the mouse, because the keyboard cannot).
  1. (nothing announced)
After. Tab to “Add to cart” and press Enter.
  1. button, Add to cart
  2. dialog, Your cart, Added to your cart: Ridgeline 40L Pack, Slate / L. Cart has 1 item.
  3. heading, Your cart, level 2

Virtual screen reader transcript (not VoiceOver). On every project we test with VoiceOver and NVDA.

Keyboard-only add to cart on the demo store, before and after, with captions. Silent keyboard-only demo. A VoiceOver version is coming. Read the transcript

What you’d get on a real project

  • A change log entry for every issue: criterion, files changed, what changed, how we verified it.
  • Changes on a duplicate or staging theme only. Your live theme stays untouched until you approve.
  • Before/after scan results at desktop and mobile widths, mapped to your issue IDs, with keyboard and screen reader notes.

See what your store needs

Book a Review with full manual testing, or compare packages and prices first.