Reviewed November 1, 2026

Accessible Size and Color Swatches That Work Without a Mouse

A swatch must be a real control, not a clickable div. Use radio inputs or buttons with accessible names that include the value, such as Size M or Color Navy, expose the selected state programmatically with aria-checked or aria-pressed, keep every swatch reachable and operable by keyboard alone, and never let color or a thin outline be the only signal of selection. Out of stock variants must be announced as unavailable, not just shown struck through.

Swatches look like the simplest widget on a product page and fail accessibility audits with embarrassing consistency. The pattern repeats across themes: a row of colored squares built from divs and click handlers, invisible to a keyboard, silent to a screen reader, with the chosen option indicated by a slightly thicker border that a low vision shopper cannot see and an assistive technology user is never told about. The shopper cannot select a size. The store calls it a theme limitation. It is a markup decision.

WCAG is specific enough to name the failures. Interactive elements need names and roles under 4.1.2, keyboard operability under 2.1.1, and information must not be conveyed by color alone under 1.4.1. A swatch group touches all three in twenty lines of code, which is why fixing it properly is such good value.

Build swatches as radio groups, because that is what they are

Choosing one size from a set is radio behavior, and native radio inputs give you keyboard support, focus management, and screen reader announcements nearly free. Style the inputs visually, hide them accessibly rather than with display none, and let the label carry the visual swatch. Arrow keys move within the group, exactly as keyboard users expect from every other radio set on the web. Custom button implementations can work, but they must reimplement roving focus and checked states by hand, and most do not.

The accessible name does the shopping work. Color Navy is a name. A background image and an aria label of swatch is a dead end. Include the product context once in the group label, using a fieldset and legend or an aria labelledby pointing at the visible Color or Size heading, and every control in the group becomes self explanatory when a screen reader user tabs straight into it.

State: selected, available, and out of stock

Selection must be programmatic, not just visual. A checked radio announces itself. A button implementation needs aria-pressed or the radio role with aria-checked, kept in sync in code, not only a CSS class. Then check the visual side honestly: if the only difference between selected and unselected is a two pixel outline in a shade close to the swatch colors, low vision users are guessing. Add a shape change, a check indicator, or a clear thickness and contrast difference, and verify it in forced colors mode, where background images and many color cues disappear entirely.

Unavailable variants are the most abused case. A struck through, greyed swatch that is still silently clickable, or worse, removed from keyboard order without explanation, leaves a shopper unsure whether their size exists. Keep it focusable or provide its status in text near the group: announce unavailable in the name, Size XL, unavailable, and say what happens instead, notify me or a size guide link. Information conveyed by a strikethrough alone fails 1.4.1 as surely as color alone does.

Test it the way the audit will

Unplug the mouse. Tab to the group, arrow between options, and confirm the focus indicator is visible on every swatch, including the white and pale colors where a light outline vanishes. Then run a screen reader, NVDA or VoiceOver, and listen to what a selection actually announces, including the price or image change that sighted users see when a variant switches. If the product image and price update silently, add an aria live announcement for the change, because the sighted feedback has an equivalent the blind shopper is owed.

Finish in forced colors mode in Windows settings or the browser emulation of it. Swatch borders, selected indicators, and focus outlines that survive forced colors will survive most real low vision setups. The ones that disappear were decoration, not communication, and they were carrying information your customers needed.

Related reading: Focus Visible Styles: The Outline Your Theme Deleted, Accessible Filters and Facets: Collection Pages a Screen Reader Can Sort, and Star Ratings That Keyboard and Screen Reader Users Can Actually Use.

Frequently asked questions

Are image swatches for patterns and prints accessible?

They can be, if each control has a text name describing the option, such as Floral print or Charcoal stripe. The image is decoration. The name is the information, and it must exist whether or not the shopper can see the pattern.

Should out of stock sizes be removed from the page?

No. Removing them hides information and breaks expectations. Mark them unavailable in text and in the accessible name, keep the state discoverable, and offer the next action, such as a notify option. A hidden size reads as a size that does not exist.

What WCAG criteria do swatch failures usually violate?

Most commonly 2.1.1 Keyboard, 4.1.2 Name Role Value, 1.4.1 Use of Color, and 1.4.11 Non text Contrast for the control boundaries and indicators. A single swatch widget can fail all four at once, which is why auditors find them so often.

Can I keep custom swatch designs and still pass?

Yes, if the underlying controls are real radio inputs or properly implemented buttons with names, states, keyboard support, and visible focus. The visual design is not the problem. Divs with click handlers pretending to be controls are.