Back to Blog
EAA Compliance for Ecommerce: Why Your Checkout Matters Far More Than Your Homepage
Most ecommerce accessibility audits start with the homepage. That is the wrong order. The checkout is what gets you sued — here is what actually breaks and how to fix it.
13 min read
Why checkout is the legal-risk concentration
Three reasons checkout-first is correct, and homepage-first is wrong:
1. The legal complaint pattern. Real complaints across the EU — German Abmahnungen, French enforcement actions, Dutch ACM filings, Austrian Schlichtungsverfahren — overwhelmingly cite checkout-blocking issues: unlabelled fields, inaccessible payment widgets, modals that trap focus, error messages that screen readers cannot reach. Homepage issues are mentioned but rarely lead the complaint.
2. The user-impact severity. A homepage that's slightly hard to navigate is annoying. A checkout that a blind user cannot complete is a discrimination event with direct financial loss for that user. Regulators and lawyers prioritise events with concrete harm.
3. The platform-defaults inversion. Most ecommerce platforms ship reasonably accessible homepages by default (clean Liquid templates, semantic Tailwind, sensible defaults). The places merchants and agencies add complexity are the places that fail — custom forms, third-party widgets, payment iframes, custom modals. These cluster around the cart and checkout, not the homepage.
If you remember nothing else: scan your checkout flow first, not your homepage.
The seven checkout failures we find on most EU stores
Order matters here too — these are ranked by how often they show up multiplied by how often they appear in actual complaints, not raw frequency.
1. Unlabelled or placeholder-only form fields
Severity: Critical · WCAG 1.3.1, 4.1.2 · axe rule: label
The single most-cited issue on ecommerce checkouts. A field that looks fine to sighted users but has nothing programmatic for screen readers.
<!-- ❌ Bad: invisible label, screen reader announces nothing useful -->
<input type="text" placeholder="Postal code">
<!-- ❌ Almost as bad: visible label not associated -->
<div>Postal code</div>
<input type="text">
<!-- ✅ Good: programmatically associated label -->
<label for="zip">Postal code</label>
<input type="text" id="zip" autocomplete="postal-code">
Notice the autocomplete="postal-code" on the good example. EAA / EN 301 549 require autocomplete attributes on form fields where they apply (WCAG 1.3.5 Identify Input Purpose, Level AA). They also help every user, not just disabled ones. Add them.
2. Card-input iframes from payment providers without accessible labels
Severity: Critical · WCAG 1.3.1, 4.1.2 · partial automation
Stripe Elements, Adyen, Mollie, and others embed payment fields in iframes. The iframe gets sandboxed, which is good for security and bad for accessibility unless the labels are explicitly configured.
For Stripe Elements specifically:
// ❌ Bad: card element with no accessible name
const card = elements.create('card');
card.mount('#card-element');
// ✅ Good: explicit aria-label, plus a visible label outside
// In your HTML:
// <label for="card-element" id="card-label">Card details</label>
// <div id="card-element"></div>
const card = elements.create('card', {
classes: { base: 'StripeElement' },
});
// Stripe v3 inherits from the parent label association if present
card.mount('#card-element');
Check your provider's accessibility documentation. Stripe, Adyen, Braintree, and Mollie all publish guidance — most agencies don't read it.
3. Cookie banner that traps focus or blocks the page
Severity: Critical · WCAG 2.1.1, 2.1.2, 4.1.2 · axe rule + manual
Discussed in our top 10 violations post. On ecommerce specifically: the cookie banner is the very first thing in the user's keyboard tab order. If it traps focus, the user never reaches the product they wanted to buy.
If you use a CMP, switch on its accessibility-tested layout. If you wrote your own banner, it almost certainly fails WCAG. Replace it with a CMP or rebuild it as a proper <dialog>.
4. Error messages that screen readers don't announce
Severity: High · WCAG 3.3.1, 4.1.3 · partial automation
The user submits the form. Validation fails. The page shows red text near the offending field. The screen reader reads nothing because the error was injected into the DOM without a live region.
<!-- ❌ Bad: error appears visually only -->
<input type="email" id="email">
<div class="error">Please enter a valid email address.</div>
<!-- ✅ Good: error is announced + associated -->
<label for="email">Email</label>
<input type="email" id="email" aria-describedby="email-error" aria-invalid="true">
<div id="email-error" role="alert">Please enter a valid email address.</div>
The role="alert" (or aria-live="assertive") makes the error announce immediately. The aria-describedby associates it with the field so the user hears the error context when they move focus back to the input.
5. Quantity steppers and custom inputs that aren't keyboard-operable
Severity: High · WCAG 2.1.1 · axe rule + manual
The classic "increment / decrement" buttons next to quantity. Often built as <div onclick> elements that work with a mouse but not with the keyboard.
<!-- ❌ Bad: divs aren't focusable, no keyboard event handler -->
<div class="qty-stepper">
<div onclick="dec()">−</div>
<input value="1">
<div onclick="inc()">+</div>
</div>
<!-- ✅ Good: native buttons + spinbutton input -->
<div class="qty-stepper">
<button type="button" aria-label="Decrease quantity" onclick="dec()">−</button>
<input type="number" min="1" value="1" aria-label="Quantity">
<button type="button" aria-label="Increase quantity" onclick="inc()">+</button>
</div>
If you must build a custom stepper, you have to wire up onclick, onkeydown for Enter and Space, focus management, and aria-label. Or just use native buttons. Always use native buttons.
6. Multi-step checkout without progress announcement
Severity: Medium-High · WCAG 4.1.3, 1.3.1 · manual
Modern checkouts often have steps: Address → Shipping → Payment → Confirmation. Sighted users see the progress indicator update; screen-reader users typically hear nothing because the step transition is just a visual class swap.
<!-- ✅ Good: live region announces step transitions -->
<div role="status" aria-live="polite" id="checkout-step-status" class="sr-only">
<!-- JavaScript updates this on step transition -->
</div>
<nav aria-label="Checkout steps">
<ol>
<li aria-current="step">2. Shipping</li>
<li>3. Payment</li>
<li>4. Review</li>
</ol>
</nav>
When the user moves from step 2 to step 3, JavaScript updates the live region: "Step 3 of 4: Payment". The user knows where they are.
7. Confirmation page with no clear "what just happened" anchor
Severity: Medium · WCAG 2.4.6, 3.3.4 · manual
After paying, the user lands on a confirmation page. The page often has the order details below the fold and a vague heading like "Thank you!". A screen-reader user lands at the top and has to navigate through nav and footer to figure out whether their order actually went through.
The fix: make the confirmation heading explicit and put it at the top of the main region.
<main>
<h1>Order #45782 confirmed — thank you, Anna</h1>
<p>Your order will ship within 2 working days. We've sent confirmation to anna@example.com.</p>
<!-- order details -->
</main>
Also: send focus to the confirmation heading on page load. Easy with React/Vue refs; one line of vanilla JS otherwise.
Platform-specific notes
What you actually get from each major platform's defaults, and where the gaps usually are:
| Platform | Default checkout | Common gaps |
|---|---|---|
| Shopify | Strong out of the box, especially Shopify Plus checkout extensibility. | Custom themes, accessibility-overlay apps, third-party "review" and "popup" apps, Liquid customisations to the cart. |
| WooCommerce | Acceptable; depends heavily on the active theme. | Older themes, custom checkout fields plugin, payment-method plugins with their own (often inaccessible) iframes, Yoast SEO breadcrumbs without proper ARIA. |
| Magento / Adobe Commerce | Mixed; recent versions improved, older B2B installs lag. | Custom UI components, the layered navigation (filtering on category pages), modals for "add to cart" confirmations. |
| BigCommerce | Adequate; Stencil themes generally OK. | Custom checkout via Checkout SDK loses most of the default accessibility; needs explicit re-implementation. |
| Shopware 6 | Improving; Storefront framework has reasonable defaults. | Custom Twig blocks, third-party plugins from the German market that often pre-date EAA awareness. |
| Custom (Next.js / Nuxt) | Whatever you built it to be. | Almost always: custom components without full keyboard support, missing form labels, modal libraries used without focus traps, unlabelled icon-only buttons. |
A two-day checkout-first plan
If you have one developer for two days, here is the pragmatic play:
- Hour 1-2: Run an automated scan against the full purchase flow: product page → add-to-cart → cart → checkout each step → confirmation. Capture the full issue list.
- Hour 3-6: Test the same flow with a screen reader (NVDA on Windows is free) using only keyboard. Note every place you got stuck.
- Day 1 afternoon: Fix all critical/serious issues on the checkout pages: form labels, error announcements, focus management on modals, autocomplete attributes.
- Day 2 morning: Fix the cart page (quantity steppers, remove buttons, save-for-later affordances).
- Day 2 afternoon: Re-test with screen reader. Publish a basic accessibility statement covering what is now compliant and what is still in progress.
You will not be 100% compliant after two days. You will be out of the highest legal-risk band — which is the only thing that matters for the next quarter while you plan a deeper engagement.
For a fuller breakdown of how the standards stack relates to all this, see our WCAG 2.1 AA vs EN 301 549 vs EAA post. For the country-specific stakes, see our EAA fines breakdown. German agency clients should also see the BFSG Abmahnung dynamic.
Scan your checkout, not just your homepage
Webply runs a free WCAG 2.1 AA scan that lets you target specific URL patterns — point it at your /checkout, /cart, and product pages, see exactly which issues will get you cited, ranked by EAA legal risk per country.
Sources and further reading
- European Commission — Directive (EU) 2019/882, Annex I (services in scope).
- French enforcement actions, November 2025: Auchan, Carrefour, E.Leclerc, Picard — covered in our EAA fines breakdown.
- Stripe Elements accessibility documentation.
- Shopify Polaris accessibility guidelines.
- WebAIM — accessible form examples and patterns.
Code examples are illustrative — production code should be tested with assistive technology in your specific framework. Not legal advice.