Accessible quantity steppers: the cart control screen readers mangle most

A cart with four line items has eight stepper buttons. If every one is named plus or minus, a screen reader user tabbing through the cart hears the same two words eight times and has to reconstruct which product each pair belongs to from memory. That is a failure of WCAG 2.1 Success Criterion 2.4.6, Headings and Labels, and of 4.1.2, Name Role Value, in spirit and usually in letter.

The fix costs nothing but care: name each button for its action and its product, increase quantity of trail socks, decrease quantity of trail socks. The WAI ARIA Authoring Practices make the same point for spinbutton patterns generally: the accessible name carries the context the visual layout gives sighted users for free.

The name problem, repeated down the page

There are two honest patterns. Pattern one is a real spinbutton: an input with role spinbutton, arrow keys that change the value, and aria valuemin, valuemax, and valuenow kept in sync. Pattern two is simpler and often better: the quantity shown as text, updated by the two buttons, with the change announced through a polite live region. Trouble starts when a build mixes them, showing a read only number that focus treats as an input, or a spinbutton whose valuenow never updates.

Pick one and implement it completely. The half pattern is what auditors flag, because assistive technology announces a control that then refuses to behave as announced. A keyboard user pressing arrow keys on a fake spinbutton gets silence, which reads as a broken site, not a design choice.

Is the quantity a spinbutton or a status?

Updating the cart usually reloads the line, recalculates totals, and re renders part of the page. If the button the shopper pressed is destroyed in that re render, focus falls back to the top of the document, and the shopper has to tab through the header and navigation to change the next quantity. That is the single most exhausting bug in accessible carts, and it appears in name brand themes.

Focus and announcement after the update

Keep reading: Promo code errors in the cart: announce the failure, keep the code, say what was wrong, Cart drawers and focus: what a keyboard user actually hits on your store.

Limits, removal, and the zero question

The correct behaviour is dull and specific: focus returns to the equivalent control after the update, and the new quantity and the new line total are announced once, politely, without interrupting. Test it by changing a quantity three times in a row with a screen reader. If you lose your place once, your shoppers lose it every time.

Decide what happens at the edges before you build. Does minus stop at one, become disabled, or remove the item at zero? Each is defensible. An undocumented behaviour is not. If minus at one removes the product, that destructive result needs a name that says so and ideally an undo, because a screen reader user who overshoots has no visual cart total to warn them the item vanished.

Stock limits need the same honesty. If only three are available, say so in text near the control and disable plus at three with the reason available to assistive technology, not just greyed out visually. A disabled button with no explanation is a dead end a sighted user can guess at and a blind user cannot.

Frequently asked questions

What does WCAG require for quantity stepper buttons?

WCAG 2.1 requires that the buttons have an accessible name describing their purpose (4.1.2 Name Role Value, supported by 2.4.6), that any value exposed to assistive technology is accurate, and that status changes are announced without moving focus (4.1.3 Status Messages). In practice: named buttons per product, synced values, polite announcements.

Should the quantity field be directly editable as well as having steppers?

It helps. A directly editable field lets keyboard and switch users set a quantity of eight without seven button presses, and it gives screen reader users an unambiguous value to review. If you offer it, it must accept typed numbers, validate gently, and update totals on commit, not on every keystroke.

Why does my cart lose focus after changing a quantity?

Because the update re renders the cart line and the focused element is removed from the page, so the browser returns focus to the document body. The fix is to restore focus to the replacement control after the update completes and to announce the new quantity through a live region.

Is it acceptable for the minus button to remove the item at quantity one?

It can be, if the button name changes to say remove at that point and the removal can be undone or is announced clearly. Silently deleting a product when a user expected the quantity to stop at one is the version auditors and users both object to.