Back in 2021, we shared details on How to Meet the New Accessibility Requirements of the Shopify Theme Store. These requirements are still in effect today and are more relevant than ever. With the European Accessibility Act set to take effect in June 2025, Shopify Merchants will require accessible storefronts that are usable by all buyers and that follow the Web Content Accessibility Guidelines.
As a reminder, when designing your Shopify themes, be sure to test for:
- Keyboard accessibility: Use the keyboard alone to test the navigability and functionality of your theme. From the homepage to checkout, all workflows must function with only the keyboard.
- Color contrast: The color contrast between background and foreground content (text, input borders, icons, focus rings, etc) should be great enough to ensure text is legible and non-text elements are perceivable.
- Focus state: Focusable elements must feature a highly visible and consistent focus style. Sighted keyboard-only, voice dictation, low-vision, and other user groups not able to use a mouse must have an understanding of the keyboard cursor position.
Re-read that post to familiarize yourself with the details for each.
Let's jump into some common Product Detail Page (PDP) accessibility issues. The accessibility of your theme PDP is key to conversion and merchant success. It represents the gateway between the buyer making the decision to add a product to the cart and ultimately moving on to checkout.
Here are three common issues found on the PDP directly impacting buyer accessibility and ultimately conversion.
1. Cart drawers missing focus management
Cart drawers are a common pattern across ecommerce storefronts. They appear as "slide-out" containers with shopping cart information when an item has been added to the cart. While visually appealing, there's a lot to consider to make these components accessible.
The problem
The primary issue here is focus management—the practice of shifting focus from one page element to another. Its purpose is to help guide the user through dynamic workflows as intended. When it comes to cart drawer components, omitting focus management can be very problematic.
In this example above, when the "Add to cart" activator is clicked, focus is not managed. Keyboard focus remains on the "Add to cart" activator. This is an issue for buyers who are blind or low-vision as they may not be aware of the presence of the cart drawer when it appears. With focus remaining on the activator and without a notification of the cart drawer availability, users are often left searching for the next step on how to proceed. This can be very confusing and disorienting. In severe cases, missing focus management could lead to task abandonment and buyers taking their business elsewhere.
The solution
To help users move from the PDP to the cart drawer and on to checkout, theme code must include JavaScript that shifts keyboard focus from the activator to the cart drawer. To simplify this approach from a developer perspective and to provide a better, more familiar user experience for buyers, it's recommended to implement the cart drawer using the modal window pattern. This pattern includes the focus management technique needed to help users along the path to checkout. It also shares the information required for blind or low-vision screen reader users to understand the current context.
Here's an overview of the HTML code changes necessary to provide context for the modal window pattern.
- Cart activator (
button
element) includes thearia-haspopup="dialog"
attribute. This provides context that activating the button will cause a modal window to appear. - Cart container (
div
element) includes therole="dialog"
attribute. This shares information that the user focus has moved from the document and is now within a modal window. - Cart container includes the
aria-modal="true"
attribute. This tells assistive technology to keep screen reader virtual cursors within the modal context until the modal is dismissed. - Cart container is labeled via
aria-label
oraria-labelledby
referencing a nearby heading. This helps provide additional context on the purpose of the modal window.
In addition to code changes, specific UX (user experience) expectations must be in place when interacting with a modal window.
Specifically, on activator click, focus shifts to the first focusable element inside the modal window (typically the close control.) As sighted user attention is brought to the visual of the modal window, so must blind or low-vision user attention. Closing the modal window (either via Close button or Esc key) will shift focus back to the activator.
For an example of an accessible cart drawer, review Shopify's Refresh theme cart drawer example and related code on GitHub:
- cart-drawer.liquid: HTML code providing structure and context for the cart drawer
- cart-drawer.js: JavaScript implementing the modal window pattern functionality
- cart-drawer.css: CSS for the cart drawer component
How to test
What does "good" accessibility of a cart drawer component look like? What do users expect? Let's review.
Using a keyboard:
- Tab to the "Add to cart" activator and press Enter (or Space.)
- When the cart drawer appears, focus should move from the activator to the cart. From here, Tab forward through the cart drawer container.
- Focus will be trapped within the modal window. Tab from the last focusable item will wrap focus to the top most focusable element. Shift + Tab will wrap to the bottom most focusable element.
- Press Esc to close the drawer which shifts focus back to the activator.
Using a screen reader:
- Use the virtual cursor to navigate to the "Add to cart" activator. There should be an additional "dialog popup" notice when the activator is focused.
- On activation, as focus moves to the cart drawer there should be a notice of, "{Cart label}, dialog" indicating focus has moved to the cart drawer.
- Use the virtual cursor to navigate forward through the cart drawer content.
- Press Esc to close the drawer, resulting in an announcement of the activator control when it receives focus.
With the user's focus and attention brought directly to the cart drawer, they'll be aware of its presence and be able to move through the cart and on to Checkout increasing conversion opportunities!
Screen reader primer
It's important to understand how to test with a screen reader on your platform of choice. For example, VoiceOver on macOS paired with Safari, NVDA on Windows paired with Chrome, or ChromeVox on ChromeOS paired with Chrome.
Here's a quick primer of common screen reader shortcuts and navigation methods.
Command | Screen reader | Key combination |
---|---|---|
Startup/shut down | VoiceOver | Cmd + F5 |
NVDA | Ctrl + Alt + N / CapsLock + Q | |
ChromeVox | Ctrl + Alt + Z | |
Narrator | Windows + Ctrl + Enter | |
Pause speaking | All | Ctrl |
Virtual cursor navigation | VoiceOver | Ctrl + Opt + → to navigate forward or Ctrl + Opt + ← to navigate backward |
NVDA | ↓ to navigate forward or ↑ to navigate backward | |
ChromeVox | Launcher + → to navigate forward or Launcher + ← to navigate backward | |
Narrator | ↓ to navigate forward or ↑ to navigate backward |
Note: Screen reader users often do not use the Tab key for navigation. As a developer, you don't need to make everything keyboard focusable. Instead, use the virtual cursor when testing for accessibility as this is the preferred method by screen reader users.
2. Sale price is not conveyed to screen reader users
For most buyers, finding a product that's on sale can be exciting and help make the decision to purchase that much easier. Therefore, it's important that all users both perceive and understand sale price information.
The problem
Sale price content is often visually displayed with stroke-through text. This denotes the regular price of the item is no longer valid. Next to this is often bold text showcasing the new sale price.
Here's a real-world example on how this content is often coded in HTML:
This visual treatment works well for sighted users. But for blind or low-vision screen reader users, there's nothing here describing the strike-through effect.
For a screen reader user this text would be described as, 45 dollars, 35 dollars.
Two different prices? What's going on here?
The solution
Let's adjust this code. We'll provide additional, visually hidden content to convey that this item is on sale—all without interrupting the intended visual design.
This code snippet adds additional context for screen reader users. By inserting two visually hidden elements—one explaining the sale price and another for the regular price—buyers will have a better understanding of this price content.
For screen reader users this will now be described as, Regular price, 45 dollars, Sale price, 35 dollars.
Much better! By placing an extra bit of contextual text before each value, the price content is now easier to perceive and understand.
For an example of accessible pricing, review Shopify's Ride theme sale product example and code on GitHub:
- price.liquid: HTML code providing structure and context for the price content
- price.css: Related CSS for the price content
How to test
What does "good" accessibility of sale price content look like? What do users expect? Let's review.
Using a screen reader:
- Use the virtual cursor to navigate through the price content. The visually hidden content should be described aloud as you move through the text.
The visually-hidden class
If your theme doesn't include the .visually-hidden
CSS class (sometimes called .sr-only
), here's the definition:
Shopify Partner TPGi has an article breaking down each line of this class.
3. Color swatch variant selector usability issues
For buyers wishing to purchase a new item, selecting the correct size, color, or other variant is critical. Therefore it's important to implement variant selectors in a way that is accessible to all.
The problem, part one
Variant selectors are often coded using HTML radio buttons. A group of radio buttons allows the user to select only one item within the group. This is a good approach as you get a lot of accessibility baked-in for free when you use native elements. The problem comes in when these elements are custom styled. Depending on how the radio button is coded to be hidden from view, this could lead to accessibility barriers.
Here's a real-world example of a custom color swatch variant selector:
Reviewing the code alone, things might seem okay. Each input
has a label, is keyboard focusable, and the native grouping allows only one item to be selected. The label element is also repurposed to supply the click/touch target. However, testing the accessibility of this component using a keyboard or screen reader show different results: each selector is skipped over entirely. What's going on?
Reviewing the CSS for this selector, we spot a big accessibility blocker:
Setting the CSS display
property to none
is a blocker. This not only removes the element from displaying visually, it also removes keyboard access and prevents discoverability by screen readers. As-is this component is completely inaccessible.
The problem, part two
Another issue that may come up with color swatch variant selectors is the use of color alone to convey information. As seen with the example above, color is the only method available to convey the difference between each variant. This can be an issue for buyers who are color blind and cannot distinguish between colors.
Without a visible text alternative, how confident might the user be in adding the product to the cart?
The solution
When custom styling form controls, such as radio buttons, it's very important to keep the elements keyboard and screen reader accessible. This way the controls are not only mouse/touch friendly, but keyboard and screen reader friendly, too.
For this particular example, we can fix this issue by adjusting the CSS. Instead of setting the radio buttons as display: none
, we can apply a different property that achieves the same visual result yet remains accessible. For instance, swapping display: none
for the appearance: none
property would be a good start. This removes system default styling of input elements, allowing for visual customizations, all the while maintaining accessibility. Alternatively, consider applying the .visually-hidden
class as defined above.
Note: There's a lot more to consider here. When applying custom styles to form controls you must also account for:
- Focus indicators: users need to see the current cursor location when navigating with a keyboard
- Visual checked/unchecked state: ensure clear visibility between checked and unchecked state
- Swatch text alternative: make sure users understand the color representation by providing a text alternative via tooltip on hover/focus
-
Media queries: various operating system settings may affect the visual design when applied—test with
forced-colors
,prefers-color-scheme
, andprefers-contrast
media queries
And for the text alternative requirement, consider adding a tooltip feature into the component code. This tooltip will showcase the color swatch label on mouse hover and keyboard focus. With this in place, color blind buyers, or anyone who needs further explanation, will have an opportunity to understand exactly what each color swatch represents.
For an example of an accessible color swatch component, review Shopify's Origin theme color swatch example and code on GitHub:
- swatch-input.liquid: HTML code providing structure and context for the swatch inputs
- swatch-input.css: Related CSS for the swatch variant component
For more details on styling form controls, check out Styling form controls on web.dev.
How to test
What does "good" accessibility of a color swatch component look like? What do users expect? Let's review.
Using a keyboard:
- Tab to the color swatch component.
- When the first variant selector has focus, press ← or → arrow key to select a variant. As focus moves from one to the next, watch for a highly visible focus state and the text alternative tooltip being displayed.
- When a selection is made, Tab away to move on to the next focusable element.
Using a screen reader:
- Use the virtual cursor to navigate to the color swatch component. It may be described as something like, "{color name}, radio button, 1 of {total}."
- Use the virtual cursor to move through each color swatch.
- Make a selection by pressing the
Space
key.
With the color swatch component properly coded, buyers will be able to use the variant selector with ease and success.
As a Shopify Partner, making your themes accessible to more people will help your theme stand out among the crowd. Be sure to test using the keyboard and a screen reader. Mention accessibility in your theme description and change logs. Merchants are actively looking for highly accessible themes to deploy to their storefronts. And with your accessible theme deployed, merchants will have increased conversion opportunities. It's win-win!
Accessibility is good for business. Let's continue making commerce accessible to everyone.
Resources
- Accessibility best practices for Shopify themes
- Getting started with retail accessibility | Fable
- W3C Accessibility Standards Overview | Web Accessibility Initiative (WAI)
- Accessibility Fundamentals Overview | Web Accessibility Initiative (WAI) | W3C
- Learn Accessibility | web.dev
- A11ycasts with Rob Dodson - YouTube
Have questions about accessibility or need help with your theme? Reach out to the Shopify Partner Support team at Shopify Partner Support.