DEV Community

AgentKit
AgentKit

Posted on • Originally published at blog.a11yfix.dev

Color and Size Swatches: The Product Page Pattern Quietly Excluding Blind Shoppers

If your store sells anything that comes in a color or a size -- a t-shirt, a pair of sneakers, a sofa, a phone case, a candle, a bag of coffee -- there is a very good chance the product page uses what designers call "swatches." Small circles painted with each color. Small squares that say "S, M, L, XL." Tiles with a tiny photo of each finish. Visually they are wonderful. They let a sighted shopper compare options at a glance, see what is in stock, and pick a variant in one tap.

They also routinely lock out every single blind shopper who lands on the page.

Here is what we have been seeing across Shopify, WooCommerce, BigCommerce, and Squarespace storefronts in 2026: the swatch ships as a <div> with a background color. There is no accessible name. There is no role="radio" or aria-checked. There is no visible focus ring. There is no way for a screen reader to know that the user has just selected "Sapphire Blue" instead of "Charcoal Grey." The shopper hears <button> or, worse, hears nothing at all and has to guess by counting clicks. The cart accepts whatever variant happens to be selected. The order ships in the wrong color. The customer leaves a one-star review or, increasingly, files an ADA Title III demand letter.

Almost none of this shows up in a standard Lighthouse or axe scan, because a colored <div> with a click handler is technically valid HTML. The scanner has no way to know that the <div> is supposed to be a product variant control. The whole class of failure lives in a blind spot that automated tools were not built to see -- which is exactly why it has become a quiet favorite of accessibility plaintiffs' law firms scouting for clean, easily-screenshot-able violations.

What a screen reader actually hears on a typical product page

Open any storefront. Find a product with three colors and four sizes. Turn on VoiceOver (Cmd-F5 on a Mac) or NVDA (free download on Windows). Tab through the variant pickers. Here is the kind of announcement we hear over and over again across themes:

"Button. Button. Button. Button. Button. Button. Button."

Seven buttons. No names. No state. No indication of which one is the selected color, which one is the selected size, which combinations are in stock, or what happens if you pick a size that is not available in the currently selected color. A sighted user sees a row of beautiful colored circles. A blind user hears static.

Slightly better themes announce:

"Blue, button. Charcoal, button. Sand, button. Small, button. Medium, button. Large, button. X-large, button."

That is an improvement -- at least the swatch now has an accessible name -- but it is still missing three critical pieces of information:

  1. Which variant is currently selected. A radio group of seven buttons is meaningless if the screen reader user cannot tell which one is "on."
  2. Which combinations are out of stock. A sighted shopper sees a greyed-out swatch with a diagonal line through it. A screen reader user hears the same "button" they hear for the in-stock options.
  3. What happens when the selection changes. When a sighted user clicks "Blue" and the price updates from $29 to $35 because Blue is the premium colorway, the screen reader user gets no announcement that the price has changed.

These three gaps are not opinions. They map to specific WCAG 2.2 Level AA criteria: 1.1.1 Non-text Content (the swatch has no text alternative), 1.4.1 Use of Color (in-stock vs out-of-stock is communicated by color alone), 4.1.2 Name, Role, Value (the selected state is not exposed programmatically), and 4.1.3 Status Messages (the price update is not announced).

Why this pattern keeps shipping

Three reasons, in roughly the order we see them on real stores:

Themes ship swatches as a visual design system, not as a component with accessibility built in. A theme author wins on screenshots, not on screen reader behavior. The Shopify theme store, the WooCommerce theme marketplace, and the Squarespace template library all reward swatches that look great in a thumbnail. The accessibility behavior is invisible in a thumbnail.

The "easy" swatch tutorials on the internet are bad. A tour of the top ten Stack Overflow answers and Shopify community posts on "how to add color swatches" returns markup using <div> and <span> with click handlers, almost never using <button> or <input type="radio">, and almost never including aria-checked or a visible focus ring. Developers copy what they find. Designers approve what they see.

Automated scans give a green light. Lighthouse, the built-in Chrome scanner, will happily report "100" on a product page where every variant control is unreadable to a screen reader, because the scanner sees <div> elements that do not violate any contrast or alt-text rule -- they are simply invisible to it as form controls.

The result is a pattern that is visible to lawyers (they screen-record a product page with VoiceOver running, paste the silent video into a demand letter, and ask for $20,000), invisible to your scanner, and present on almost every store with a theme older than two years.

What an accessible swatch actually looks like

The right pattern is well documented and not new. The W3C ARIA Authoring Practices Guide has been publishing a "radiogroup" pattern for over a decade. Here is the short version, written for someone who is going to ask their theme developer or a Shopify expert to fix it:

A variant picker is a radio group. Each swatch is a radio button. The whole group has a label ("Color" or "Size"). Each radio has a label that includes the color name or size, not just the visual cue. Exactly one radio is checked at a time, communicated via aria-checked (or, for native <input type="radio">, the checked attribute). Each radio has a visible focus ring when it receives keyboard focus -- not the browser default that the theme has stripped away with outline: none, an actual visible focus ring that meets WCAG 2.4.7 and 2.4.11.

Out-of-stock variants are marked with text, not just color. A common pattern is to render the variant with a strikethrough plus an aria-disabled="true" attribute and an aria-label like "Sand, out of stock". A user who relies on assistive technology hears "Sand, out of stock, radio button" instead of hearing the same "button" they would hear for an in-stock option.

Price updates and stock updates that happen when the user changes the selected variant are announced via a aria-live="polite" region elsewhere on the page. The user picks "Blue" and a fraction of a second later their screen reader says "Price updated to $35." The user picks "Sand" and the screen reader says "Sand, out of stock, choose a different color."

That is the entire pattern. It does not require a redesign. It does not require new graphics. It does not require a separate "accessibility mode" of the site. It requires the swatch markup to use the right elements and the right attributes, which is a one-day theme tweak for most stores.

What you can do this week, by platform

You do not need to be a developer to ship this fix -- you need to know what to ask for. Here is the minimum your store needs, in plain English, organized by platform.

Shopify. Open your theme editor and check whether your product page uses the platform's "Buttons" variant style, "Dropdowns," or "Pills/Swatches." The Dawn-family default themes (Dawn, Crave, Refresh) ship with accessible radio-group variant pickers when "Buttons" is selected, and the swatch behavior is also accessible in recent updates. If your store uses an older third-party theme (Brooklyn, Empire, Turbo, Symmetry pre-2024), you almost certainly have the broken pattern. Ask your theme developer to "convert the variant swatches to a radiogroup with proper aria-checked and a visible focus ring." Estimate: half a day to one day of developer time. If you do not have a developer, the Shopify Experts directory will quote this fix at $200-$500 for most themes.

WooCommerce. The default WooCommerce variation dropdown is technically accessible -- a real <select> element with <option> children works correctly with every screen reader. The accessibility breaks when a "swatches plugin" replaces the dropdown with a custom UI. The most common offenders are early versions of Variation Swatches for WooCommerce and several abandoned plugins; the current top plugins in this category have improved meaningfully but still ship configurations that drop the focus ring or omit the selected-state attribute. Test your specific configuration with the keyboard (Tab to the swatch group, arrow keys between options, Space to select) and with a screen reader before you assume your plugin handles this correctly.

BigCommerce and Squarespace. Both platforms have native variant pickers that ship reasonably accessibly when used as designed. The failures here almost always come from custom code or third-party apps that override the default variant UI. If your store has custom variant tiles, treat them the same way you would a custom Shopify theme: get the markup audited.

Custom-built stores (Next.js, Astro, Remix, Rails). This is where the broken <div> pattern is most common, because the developer wrote the variant picker from scratch and did not pull in a tested radio-group component. Ship one of the open-source headless components (Radix UI's RadioGroup, React Aria's useRadioGroup, Headless UI's RadioGroup) or rebuild the pattern by hand from the ARIA Authoring Practices Guide. Every team that has done this in production has come back to us and said the same thing: it took a single developer between half a day and a day, and the resulting component is more usable for everyone, including sighted shoppers on mobile who now have a focus ring they can see and a tap target that meets WCAG 2.5.8.

The conversion case

We have looked at enough storefronts now to say with confidence that this is not just an accessibility story -- it is a conversion story. Every time we audit a product page with broken swatches, we find:

  • Mobile shoppers tapping the wrong variant because the target is too small and there is no visible feedback when the swatch is selected (WCAG 2.5.8 target size, 2.4.11 focus appearance).
  • Customers ordering the wrong color and contacting support to return the item, which costs the merchant the shipping label both ways plus the staff time.
  • Repeat customers who used to rely on a built-in browser autofill assistant or a third-party tool (extensions for low-vision users, screen magnifiers, switch control on iOS) who quietly stopped coming back after a theme update broke the variant picker for them.

You will not see any of this in your analytics, because the customers who hit it do not file a support ticket -- they just leave. The shape of the lost revenue is invisible until you instrument for it, which most stores do not.

The legal case

Plaintiff law firms specializing in ADA Title III digital accessibility complaints are now routinely scanning product pages for exactly this pattern, because the screenshots and the screen recordings make a clean case. A demand letter that includes a 20-second video of VoiceOver saying "button, button, button, button" over a row of beautiful colored swatches is the kind of evidence that settles for $5,000 to $25,000 in the United States and that, after June 28, 2025, can also trigger enforcement under the European Accessibility Act for any product sold to consumers in the EU. None of this is legal advice, and you should consult a qualified attorney for your jurisdiction, but the pattern is real and the trend is up.

What to do in the next 30 minutes

You can audit your own store right now, no tools required. Open a product page. Use only your keyboard -- no mouse, no trackpad. Tab to the variant pickers. Try to select a different color. Try to select a different size. Try to add the result to your cart. Did your keyboard focus ring stay visible the whole time? Did the swatch you selected look different from the others, in a way that does not depend only on color? Did the "Add to Cart" button update to reflect your new selection?

Then open VoiceOver (Cmd-F5 on Mac) or NVDA (free at nvaccess.org). Navigate the same page with your eyes closed. If you cannot tell which color is currently selected, which size is currently selected, or whether your chosen combination is in stock -- that is the bug. Take a 30-second screen recording. Send it to your theme developer with one sentence: "Please convert this variant picker to a proper accessible radio group." It is the highest-leverage single fix most product pages can ship this quarter.

We're building a simple accessibility checker for non-developers -- no DevTools, no jargon. Join our waitlist to get early access.

Related Reading

Top comments (0)