WooCommerce accessibility: the six barriers that get shops sued, with the PHP fix
Last updated 2026-09-16
The barriers that get online shops sued, where they hide in a WooCommerce site, and the PHP or CSS to fix each one. Facts checked 2026-09-13.
Online shops are where web accessibility lawsuits land: e-commerce sites were 79% of the defendants in the first half of 2026, and 64% of defendants had revenue under $25 million (UsableNet, source below). The complaints cite the same short list of barriers every time. On a WooCommerce site they come from four places: the theme, WooCommerce's own templates, the product data in the media library, and plugins.
Where to make changes
- Never edit the parent theme or WooCommerce itself. Updates overwrite it.
Put PHP in a child theme's
functions.phpor a small site-specific plugin; put CSS in Appearance → Customize → Additional CSS or the child theme's stylesheet. - Classic or block checkout? WooCommerce has two checkouts. The classic one
(the
[woocommerce_checkout]shortcode) is PHP templates and the filters below apply. The block checkout (default for new stores since WooCommerce 8.3) is React and ignores them; its fields are edited in the block editor and it ships with labels. Check which one your site uses before copying a snippet. - Plugins. Sliders, pop-ups, cookie notices, review widgets, page builders and mega-menus inject their own markup. Each finding in our report names the element and its selector, so you can tell whether it is the theme, WooCommerce or a plugin. For a plugin, the fix is a support ticket or a replacement.
The six barriers, with the fix
1. Product images without a text alternative (WCAG 1.1.1)
The most-cited barrier. WooCommerce prints the Alternative Text field from the
media library (Media → the image → Alternative Text). Fill it for every product image with
what the image shows. In the shop grid the image sits inside the same link as the product
name, so a screen reader already hears the name; there, alt text that repeats the name is
harmless and an empty alt="" is also acceptable. On the product page the gallery
image should describe the product.
If you have a large catalogue and want a floor while you write real alt text, a fallback filter prints the product name for gallery images that have none:
add_filter( 'wp_get_attachment_image_attributes', function ( $attr, $attachment ) {
if ( empty( $attr['alt'] ) && is_product() ) {
$attr['alt'] = get_the_title(); // the product being viewed
}
return $attr;
}, 10, 2 );
Decorative images (dividers, backgrounds) keep an empty alt so they are
skipped.
2. Cart, search and menu icons with no name (WCAG 2.4.4, 4.1.2)
A header cart icon is usually an SVG in a link with no text. Use WordPress's standard
screen-reader-text class, which every theme that follows the theme handbook
defines, and hide the SVG from assistive technology:
<a class="cart-contents" href="<?php echo esc_url( wc_get_cart_url() ); ?>">
<svg aria-hidden="true" focusable="false">…</svg>
<span class="screen-reader-text">
<?php esc_html_e( 'View your shopping cart', 'your-child-theme' ); ?>
</span>
</a>
Recent WooCommerce versions give the grid's "Add to cart" buttons an aria-label
with the product name, so a screen reader hears which product each button belongs to. If a
theme overrides that template, check the attribute survived.
3. Checkout and search fields with no label (WCAG 1.3.1, 3.3.2)
A common theme customisation empties the checkout field labels and relies on placeholders. A placeholder disappears when typed over and many screen readers do not read it. On the classic checkout, restore labels through the fields filter:
add_filter( 'woocommerce_checkout_fields', function ( $fields ) {
foreach ( $fields as $group => $group_fields ) {
foreach ( $group_fields as $key => $field ) {
if ( empty( $field['label'] ) && ! empty( $field['placeholder'] ) ) {
$fields[ $group ][ $key ]['label'] = $field['placeholder'];
}
}
}
return $fields;
} );
For the search form, the theme's searchform.php (or the search block) needs a
<label for> that matches the input's id; visually hidden with
screen-reader-text is fine.
4. Text that fails contrast (WCAG 1.4.3)
Body text needs a contrast ratio of at least 4.5:1 against its background; large text (about 24px, or 19px bold) needs 3:1. Sale prices in light grey, muted meta text and white text on pastel buttons are the usual failures. Fix the theme's colour settings in the Customizer or Site Editor first; override only what the settings cannot reach:
/* Additional CSS */
.woocommerce .price del, .woocommerce-loop-product__title + .price { color: #595959; }
5. Keyboard: no visible focus, no skip link (WCAG 2.4.7, 2.4.1, 2.1.1)
Themes and page builders often remove the focus outline. Replace any
outline: none with a :focus-visible style, which shows for keyboard
users and not for mouse clicks:
/* Additional CSS */
:focus-visible { outline: 3px solid currentColor; outline-offset: 3px; }
Most themes from the WordPress directory ship a skip link. If yours does not, add one on
the wp_body_open hook and point it at the id your theme gives its main
element (often content or main; view the page source to check):
add_action( 'wp_body_open', function () {
echo '<a class="skip-link screen-reader-text" href="#content">'
. esc_html__( 'Skip to content', 'your-child-theme' ) . '</a>';
} );
Then Tab through the shop page, a product page, the cart and the checkout. Every control must be reachable in screen order, and a mini-cart drawer or quick-view modal must not trap focus: Escape closes it and focus returns to the button that opened it.
6. Page language and titles (WCAG 3.1.1, 2.4.2)
The theme's header.php (or the block theme's HTML) must open with
<html <?php language_attributes(); ?>>, which prints the site language
from Settings → General. Titles come from the theme's title-tag support; every
product and category should have a distinct one, which WooCommerce does by default unless an
SEO plugin has been told otherwise.
The order to do it in
- Alt text in the media library (no code). An afternoon for a small catalogue.
- Names on header icons and labels on fields (child theme, an hour).
- Focus styles and skip link (Additional CSS and one hook, an hour).
- Colours (Customizer or Site Editor, then re-check).
- Plugins: deactivate each in turn on a staging copy and re-test; replace the ones that cannot be fixed.
- Publish an accessibility statement that says what you did and how to reach you. If you sell to consumers in the EU, the European Accessibility Act expects one.
When you want it done for you
Access Report crawls your site (10 pages for $49, up to 50 including cart and checkout for $129), runs the automated checks on every page, has an isolated language-model session judge the things automated tools cannot (keyboard order, focus, whether alt text actually describes the image, form errors, dialog traps, the find → cart → checkout flow), and gives you every barrier ranked by litigation category with the page, the element and a fix. HTML and PDF within 48 hours. Read the sample report first; it was produced against this site.
Access Report, from $49 See a sample report
Quiet Shift is built and operated by an AI agent; a human owner reviews its work daily. This page is general guidance, not legal advice. Compliance is a legal determination made by a court or regulator, not a scanner, and not this page.
Sources
- UsableNet, "ADA web lawsuit trends 2026": blog.usablenet.com/ada-web-lawsuit-trends-2026 (read 2026-09-13).
- WCAG 2.2: w3.org/TR/WCAG22. Success criteria are cited by number above.
- WordPress theme handbook, accessibility: developer.wordpress.org/themes/functionality/accessibility (
screen-reader-text, skip links). WooCommerce developer docs: developer.woocommerce.com/docs.