Storefront accessibility¶
storefront-accessibility
Build product, cart, and checkout pages that meet WCAG 2.2 AA: keyboard use, visible focus, labels and autocomplete, announced errors and cart updates, contrast, and target size. Use when building or reviewing storefront UI, forms, filters, carousels, or checkout for accessibility.
Version 0.3.2 · MIT · Source · Rule
Install this skill
Copy the skill and its rule into your project:
The skill goes to .agents/skills/ and the rule to .agents/rules/. See Command line for other directories.
A shopper who cannot reach the buy button with a keyboard, or does not hear that the cart changed, cannot buy. Aim for WCAG 2.2 level AA on every step from search to order confirmation. The success criteria that matter most in a store are listed in the WCAG checklist.
Procedure¶
- Use native elements first:
<button>for actions,<a href>for navigation,<select>,<input type="radio">, and<fieldset>with<legend>for option groups. Add ARIA only where no native element fits. - Make every action work with a keyboard in a logical order, with a visible focus indicator that is not hidden behind sticky headers or cookie banners.
- Give every form field a visible
<label>and the rightautocompletetoken (given-name,postal-code,email,tel,cc-number). - Announce changes that happen without a page load: "Added to cart", a new cart total, filter result counts. Use a polite live region (
role="status"oraria-live="polite"). - On a form error, name the field and the fix in text, link the error summary to the fields, set
aria-invalid="true", and move focus to the summary or the first invalid field. - Check color contrast: 4.5:1 for normal text, 3:1 for large text and for focus indicators, borders of inputs, and icons that carry meaning.
- Make touch and click targets at least 24 by 24 CSS pixels, or space them so the 24 pixel circle around each does not overlap another.
- Test with a keyboard only, a screen reader, 200 percent zoom, and an automated checker on the product, cart, and checkout templates.
Product pages¶
- Variation pickers are radio groups or selects with a group label ("Size"). A color swatch has a text name, not only a color. Unavailable options say so in text.
- Price changes after picking a variation are announced.
- Images have
alttext that says what differs between them ("Back view, blue"). Decorative images havealt="". - Carousels have pause controls, do not auto-advance faster than a shopper can read, and can be used with a keyboard.
Cart and checkout¶
- Quantity steppers are buttons with names ("Increase quantity of Blue mug"), and the input accepts typed values.
- Do not ask for the same information twice in one flow. Offer "same as shipping" for billing (WCAG 3.3.7 Redundant Entry).
- Do not require solving a puzzle or remembering a code to sign in or pay, unless an alternative exists (3.3.8 Accessible Authentication). Allow password managers and pasting one-time codes.
- Session timeouts warn the shopper and let them extend, so a slow shopper does not lose the cart.
- The order confirmation page has a clear heading and the order number as text.
Gotchas¶
<div onclick>buttons are not focusable and are not announced as buttons.- A placeholder is not a label. It disappears when typing starts and often fails contrast.
outline: nonewithout a replacement focus style hides where the keyboard is.- Opening a mini-cart drawer without moving focus into it, or without returning focus when it closes, strands keyboard users.
- Infinite scroll without a "load more" button hides the footer and is hard to navigate by keyboard.
- Disabled "Place order" buttons with no explanation leave shoppers stuck. Keep it enabled and explain errors on submit.
Verification¶
- The whole purchase, from search to confirmation, completes with a keyboard only.
- A screen reader announces the add-to-cart result and the new cart count.
- Submitting checkout with an empty postal code moves focus to an error that names the field.
- Text and focus indicators meet the contrast ratios above.
- The page is usable at 200 percent zoom and 320 CSS pixels wide without horizontal scrolling.
Evaluation¶
Worked examples and the checks they must satisfy are in evals/tasks.json.
References¶
WCAG 2.2 checklist for stores¶
Level A and AA success criteria that storefronts most often fail. Numbers refer to WCAG 2.2.
| Criterion | Level | In a store |
|---|---|---|
| 1.1.1 Non-text Content | A | Product image alt, icon buttons with names, swatches with text |
| 1.3.1 Info and Relationships | A | Headings, lists, tables for size charts, fieldset and legend for options |
| 1.3.5 Identify Input Purpose | AA | autocomplete on address, email, phone, and payment fields |
| 1.4.3 Contrast (Minimum) | AA | 4.5:1 text, 3:1 large text, including sale prices and badges |
| 1.4.10 Reflow | AA | Usable at 320 CSS pixels wide |
| 1.4.11 Non-text Contrast | AA | 3:1 for input borders, focus rings, and meaningful icons |
| 2.1.1 Keyboard | A | Filters, swatches, carousels, mini-cart, and payment fields |
| 2.2.1 Timing Adjustable | A | Cart or checkout timeouts can be extended |
| 2.2.2 Pause, Stop, Hide | A | Auto-advancing carousels and countdown banners |
| 2.4.3 Focus Order | A | Drawers and modals trap and return focus |
| 2.4.7 Focus Visible | AA | A visible focus style everywhere |
| 2.4.11 Focus Not Obscured (Minimum) | AA | Sticky headers and cookie banners do not cover focus |
| 2.5.8 Target Size (Minimum) | AA | 24 by 24 CSS pixels, or enough spacing |
| 3.3.1 Error Identification | A | Errors in text, naming the field |
| 3.3.3 Error Suggestion | AA | Say how to fix it: "Enter a 5-digit postal code" |
| 3.3.7 Redundant Entry | A | "Same as shipping" for billing |
| 3.3.8 Accessible Authentication (Minimum) | AA | No puzzle or memory test to sign in. Allow paste and password managers. |
| 4.1.2 Name, Role, Value | A | Custom controls expose role and state, such as aria-expanded and aria-pressed |
| 4.1.3 Status Messages | AA | Cart updates and result counts in a live region |
Live region pattern¶
<div role="status" class="visually-hidden" id="cart-status"></div>
<script>
function announceCart(message) {
const region = document.getElementById("cart-status");
region.textContent = "";
requestAnimationFrame(() => { region.textContent = message; });
}
// announceCart("Blue mug added to cart. Cart has 3 items.");
</script>
The region must exist in the page before the message is written, or some screen readers miss it.
Evaluation¶
Fixtures from evals/tasks.json. See evaluation fixtures for how the checks work.
add-to-cart-announcement¶
The add-to-cart button updates a mini-cart badge with JavaScript. Make the result accessible to screen reader and keyboard users.
Must include: <button>, role="status", focus
Must not include: <div onclick
Worked example
Use a real <button> for add to cart so it is focusable and announced as a button. After the request succeeds, write "Blue mug added to cart. Cart has 3 items." into a role="status" live region that already exists in the page. Update the badge text too, with a visually hidden "items in cart" label.
Leave focus on the button after adding. If the mini-cart drawer opens, move focus into it, trap focus while it is open, and return focus to the button when it closes.
checkout-errors¶
Review a checkout form whose fields use placeholders as labels and show errors only as red borders. List the fixes.
Must include: <label>, autocomplete, aria-invalid, contrast
Must not include: placeholder is enough
Worked example
Give every field a visible <label> and keep the placeholder only for an example value. Add autocomplete tokens such as given-name, address-line1, postal-code, email, and tel.
On submit, show an error summary with links to each invalid field, write each error in text next to the field, set aria-invalid="true", and move focus to the summary. A red border alone fails for color-blind shoppers, so add an icon and text, and check the border and text contrast against the background.