Tabpath · Accessibility Audit

Nordvik Supply Co.

Scanned 23 August 2026 Standard WCAG 2.2 AA Engine axe-core 4.13 + Tabpath keyboard pass Platform accessiBe widget detected

This is a demonstration report. "Nordvik Supply Co." is a fictional store built to exercise the scanner. Every number below is real output from a real scan of that page — nothing here is illustrative or hand-written. We do not publish audits of real businesses without their consent.

This store is running an accessiBe accessibility widget — and its Add to Cart button cannot be reached by a keyboard at all. A customer who does not use a mouse can browse the shop and cannot buy from it.

35
Failing elements across the page
3
Critical failures blocking purchase
6
Controls a keyboard cannot operate
4
Controls a keyboard can reach

What a keyboard user actually experiences

We tab through the page the way a customer without a mouse would, and record every stop. This is the test automated scanners skip — and it is where the real damage shows up.

Today

4 stops · in this order

  1. 1 (no accessible name) input
  2. 2 (no accessible name) input
  3. 3 click here a
  4. 4 click here a

Never reached: Shop, About, Cart, Add to cart, Subscribe, Close promotion. Both product links announce only as “click here”.

After remediation

11 stops · in this order

  1. 1 Skip to main content a
  2. 2 Shop a
  3. 3 About a
  4. 4 Cart, 2 items a
  5. 5 Add Winter Collection sweater to cart button
  6. 6 View the Fjord Beanie a
  7. 7 View the Bergen Scarf a
  8. 8 (no accessible name) input
  9. 9 (no accessible name) input
  10. 10 Subscribe button

Findings and the code that fixes them

11 distinct issues, ordered by what costs you customers first. Each patch below is the exact replacement markup — not a description of one.

critical 1 instance

Add to cart is removed from the tab order

WCAG 2.2 · 2.1.1 Keyboard (Level A)

tabindex="-1" takes the primary purchase button out of the keyboard path entirely. A keyboard-only customer can reach your product page and cannot buy from it. This is a revenue defect before it is a compliance defect.

Currently
<button class="cta" tabindex="-1">Add to cart</button>
Replace with
<button class="cta" type="button">Add Winter Collection sweater to cart</button>

Why this version: Also name the button for what it adds — a screen reader user listing buttons otherwise hears "Add to cart" repeated once per product.

critical 5 instances

Controls that a keyboard cannot reach at all

WCAG 2.2 · 2.1.1 Keyboard (Level A)

These are <div> and <span> elements with click handlers. A mouse can use them; a keyboard cannot focus them and a screen reader does not announce them as controls. On this store that includes the main navigation, Cart, Subscribe, and the modal close button.

Currently
<span onclick="location.href='/cart'">Cart (2)</span>
<div  onclick="submitForm()" class="cta">Subscribe</div>
Replace with
<a href="/cart">Cart, 2 items</a>
<button type="submit" class="cta">Subscribe</button>

Why this version: Native <a> and <button> give you focusability, keyboard activation, and the correct announced role for free. Every ARIA workaround here is worse than the element it replaces.

critical 2 instances

Product images have no text alternative

WCAG 2.2 · 1.1.1 Non-text Content (Level A)

A shopper using a screen reader hears "image" or the raw filename where your product should be. They cannot tell what they are buying, so they leave.

Currently
<img src="sweater.jpg" width="300" height="200">
Replace with
<img src="sweater.jpg" width="300" height="200"
     alt="Cream cable-knit wool sweater with a folded collar">

Why this version: Describe what the product looks like, not the file. Skip "image of" — screen readers already announce the role. Decorative images get alt="" so they are skipped entirely.

serious 1 instance

The promotional modal has no accessible name

WCAG 2.2 · 4.1.2 Name, Role, Value (Level A)

A screen reader announces "dialog" with no indication of what it wants. The customer cannot tell whether it is a discount offer or a checkout error.

Currently
<div role="dialog">
  <span class="close" onclick="closeModal()">×</span>
Replace with
<div role="dialog" aria-modal="true" aria-labelledby="promo-title">
  <button class="close" type="button" aria-label="Close promotion">×</button>

Why this version: aria-modal="true" also tells assistive tech to ignore the page behind the dialog, which stops the screen reader wandering out of it.

serious 14 instances

Text does not have enough contrast against its background

WCAG 2.2 · 1.4.3 Contrast (Minimum) (Level AA)

Prices and navigation are unreadable for customers with low vision, and for anyone on a phone in daylight. This is the single most common failure on the web and the easiest to fix.

Currently
.bar   { background:#2b6cb0; color:#a9c7e8; }  /* 3.1:1 — fails */
.price { color:#b3b3b3; }                      /* 2.3:1 — fails */
Replace with
.bar   { background:#1a4a80; color:#ffffff; }  /* 8.6:1 — passes */
.price { color:#4a4a4a; }                      /* 8.9:1 — passes */

Why this version: Body text needs 4.5:1. Text at 24px, or 19px bold, needs only 3:1. We pick the nearest passing colour to your brand palette so the design does not change perceptibly.

serious 1 instance

The page does not declare its language

WCAG 2.2 · 3.1.1 Language of Page (Level A)

Screen readers guess the pronunciation rules. English content read with a French voice engine is close to unintelligible. One attribute fixes the whole page.

Currently
<html>
Replace with
<html lang="en">

Why this version: Use the specific tag if you serve a regional variant: lang="en-GB", lang="es-MX".

serious 2 instances

Positive tabindex values override the natural keyboard order

WCAG 2.2 · 2.4.3 Focus Order (Level A)

Keyboard focus jumps around the page in an order that does not match what the customer sees. On your newsletter form, focus lands on Email before First name.

Currently
<input type="email" placeholder="Email address" tabindex="3">
<input type="text"  placeholder="First name"    tabindex="1">
Replace with
<label for="fn">First name</label>
<input id="fn" type="text"  name="firstName" autocomplete="given-name">
<label for="em">Email address</label>
<input id="em" type="email" name="email"     autocomplete="email">

Why this version: Any tabindex above 0 is a bug. Order the DOM correctly instead and delete the attribute.

serious 1 instance

No skip link

WCAG 2.2 · 2.4.1 Bypass Blocks (Level A)

Without one, a keyboard user tabs through the full header on every single page before reaching content.

Currently
<body>
  <div class="bar"> … nav … </div>
Replace with
<body>
  <a class="skip" href="#main">Skip to main content</a>
  <header> … nav … </header>
  <main id="main">

Why this version: .skip { position:absolute; left:-9999px } and .skip:focus { left:8px; top:8px } keeps it invisible until tabbed to.

moderate 1 instance

Heading levels skip a step

WCAG 2.2 · 1.3.1 Info and Relationships (Level A)

Screen reader users navigate by jumping between headings, the way a sighted shopper skims. Skipped levels make the page outline lie about its own structure.

Currently
<h2>Handmade Norwegian Wool</h2>
<h4>Winter Collection</h4>
Replace with
<h1>Handmade Norwegian Wool</h1>
<h2>Winter Collection</h2>

Why this version: Heading level is structure, not size. Style with CSS; never pick a heading tag for how big it looks.

moderate 8 instances

Page content sits outside any landmark

WCAG 2.2 · 1.3.6 / best practice

Landmarks are how a screen reader user jumps straight to the main content or the navigation. Without them, every visit starts by tabbing through the entire header.

Currently
<div class="bar"> … </div>
<div class="hero"> … </div>
Replace with
<header><nav aria-label="Primary"> … </nav></header>
<main id="main"> … </main>

Why this version: Use one <main> per page. Give each <nav> an aria-label if there is more than one.

moderate 1 instance

The page has no H1

WCAG 2.2 · 1.3.1 Info and Relationships (Level A)

Nothing identifies what the page is about at the top of its outline. This also costs you in search ranking.

Currently
<h2>Handmade Norwegian Wool</h2>
Replace with
<h1>Handmade Norwegian Wool</h1>

Why this version: Exactly one H1 per page, matching the page title.

Verification

We apply the patches, re-run the identical scan, and publish the delta. If these numbers do not move, you have not been charged for anything.

MeasureBeforeAfter
Failing element instances290
Critical failures10
Serious failures40
Automated checks passed2742
Controls a keyboard can reach411
Controls a keyboard cannot operate50
Skip link presentnoyes
Page landmarks03

What this audit does not cover

Read this part. Most vendors leave it out.

Automated testing catches roughly a third of the WCAG success criteria — Deque's own research puts machine-testable criteria at about 16 of 50. Our keyboard pass extends that meaningfully, but it does not reach everything. Specifically, this report does not assess:

  • Whether alt text is accurate — only whether it exists and is not obviously junk
  • Screen reader announcement quality on dynamic updates, live regions, and cart state changes
  • Reading order and comprehension for cognitive accessibility
  • Video captions, audio description, and media alternatives
  • Anything behind login, in checkout, or on pages we were not given

And to be explicit: this is engineering work, not legal advice, and no vendor — including us — can guarantee that any website is immune from a lawsuit. Anyone who tells you otherwise is selling you the thing the FTC fined accessiBe $1 million for saying in 2025. What we can do is fix the defects, show you the before and after, and give you a dated record that you acted.