Nested interactive
Moderate effortFound on 15% of audited stores.
Remove or restructure focusable elements nested inside interactive controls so that no interactive element contains another focusable child.
What it is
WCAG Success Criterion 4.1.2 requires that every interactive component on a page has a clear name, role, and value that assistive technologies can understand. A "nested interactive" violation means a clickable or focusable element — like a button, link, or input — contains another focusable element inside it. For example, a product card that is wrapped in a `<a>` tag but also contains a separate "Add to Cart" `<button>` inside it, or a `<button>` that wraps a `<label>` and an `<input>`. HTML does not allow interactive elements to be nested inside other interactive elements — it is invalid markup that breaks predictable keyboard and screen-reader behavior.
Why it matters
Keyboard-only users and screen-reader users (blind shoppers, people with motor disabilities) navigate your store by tabbing through focusable elements. When interactive elements are nested, the browser renders the structure unpredictably: focus may skip the inner element, become trapped, or announce confusing information (e.g. reading an entire product card as one gigantic link). This directly prevents some customers from adding items to their cart, completing checkout, or using navigation menus — losing you real revenue. In many jurisdictions (US ADA, EU EAA, UK PSBAR) inaccessible ecommerce sites expose businesses to legal complaints and lawsuits. Fixing nested interactive elements is one of the most impactful keyboard-accessibility improvements you can make.
How to fix it
- Identify the offending markup: locate the outer interactive element (e.g. a wrapping <a> or <button>) and the inner focusable descendant (e.g. a nested <button>, <a>, <input>, or element with tabindex='0') in your theme or page templates.
- Decide which element should be the primary interactive control. In most ecommerce cases (e.g. a clickable product card), the correct pattern is a non-interactive container (e.g. a <div> or <li>) with a single visible interactive element (the product title as an <a>) rather than wrapping the entire card in an <a>.
- Restructure the HTML so that interactive elements are siblings or cousins, never ancestors of one another. For a product card with both a title link and an Add to Cart button, place both as direct children of a non-interactive wrapper — do not wrap the whole card in an <a>.
- If you need the entire card to appear clickable, use a CSS technique: make the title <a> fill the card visually with position:absolute/inset:0, and keep the Add to Cart <button> above it with a higher z-index and its own explicit focus style. This keeps the DOM valid while giving the visual affordance of a clickable card.
- Verify no element has tabindex='0' or tabindex='-1' set on a child inside a native interactive element; remove those attributes or move the child outside the interactive parent.
- Test the fix: tab through the affected component with a keyboard only (no mouse) and confirm focus lands on each control in a logical order with no skipped or trapped stops; then test with a screen reader (NVDA+Firefox or VoiceOver+Safari) to confirm each control is announced correctly.
<!-- ❌ WRONG: <a> wrapping a <button> — invalid nested interactive -->
<a href="/products/widget">
<img src="widget.jpg" alt="Blue Widget">
<span>Blue Widget</span>
<button type="button">Add to Cart</button> <!-- nested interactive! -->
</a>
<!-- ✅ CORRECT: non-interactive wrapper; link and button are siblings -->
<div class="product-card">
<!-- Stretch the link to cover the card visually with CSS -->
<a href="/products/widget" class="card-link">
<img src="widget.jpg" alt="Blue Widget">
<span>Blue Widget</span>
</a>
<!-- Button sits above the stretched link via z-index -->
<button type="button" class="add-to-cart">Add to Cart</button>
</div>
<!-- CSS for the "full-card link" pattern -->
<style>
.product-card { position: relative; }
.card-link::after {
content: '';
position: absolute;
inset: 0; /* covers the full card */
z-index: 0;
}
.add-to-cart { position: relative; z-index: 1; }
</style>Fix it on your platform
Pick your platform for the exact steps.
How to fix nested interactive on Shopify
- In your Shopify Admin go to Online Store → Themes → (your active theme) → Actions → Edit code.
- Open the file most likely to contain the offending component. Product cards are typically in snippets/product-card.liquid or snippets/card-product.liquid (Dawn theme). Navigation dropdowns are in snippets/header.liquid or sections/header.liquid.
- Search for the outer interactive wrapper (e.g. <a … class="card__inner"> or <button>) and look for any focusable child element nested inside it.
- Restructure the Liquid template following the 'sibling' pattern in the code example above: replace the wrapping <a> with a <div>, then add a dedicated <a> for the product title/image and keep the Add to Cart button as a sibling.
- Save the file, then preview the theme and tab through the product grid with a keyboard to confirm focus order is correct.
- If you use a page-builder app (like Shogun or PageFly), open the page in that app's editor, select the block, and edit its HTML/custom code section directly using the same pattern.
How to fix nested interactive on WooCommerce
- In your WordPress Admin go to Appearance → Theme File Editor (or use a child theme via FTP/SFTP).
- Product cards are rendered by woocommerce/templates/content-product.php (copy to your-theme/woocommerce/content-product.php to safely override it).
- Open that file and find any wrapping <a> or <button> that contains another focusable element inside it.
- Refactor using the sibling pattern: use a <div class="product-card"> wrapper, move the product link and Add to Cart button as direct children rather than nested.
- If your theme uses a custom product card template, check your-theme/woocommerce/ for overrides and apply the same fix there.
- Flush any caching plugin (e.g. WP Super Cache, W3 Total Cache) after saving, then test keyboard navigation on the shop page.
How to fix nested interactive on BigCommerce
- In your BigCommerce Admin go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Product cards are in templates/components/products/card.html (Cornerstone theme). Open that file.
- Search for a wrapping <a> or <button> that encloses another interactive element.
- Apply the sibling restructure: change the outer wrapper to a <div>, keep the product title as its own <a>, and ensure the quick-add or wishlist buttons are siblings, not children of the title link.
- Save and preview. Use the Stencil CLI locally for faster iteration if you have developer access.
- Test keyboard tab order on the category/product listing pages.
How to fix nested interactive on Wix
- In the Wix Editor, click on the product gallery or the specific component flagged.
- For Wix Stores product grids, click the grid → Settings → Layout, and check whether you have custom 'Product Page' designs with overlapping buttons. Wix Stores grids do not expose direct HTML, so use Velo (Dev Mode) to override rendering.
- Enable Dev Mode (left panel → Dev Mode → Turn on Dev Mode). Open the relevant repeater or product widget in the code panel.
- In the element's code, ensure buttons inside the repeater items are not wrapped in anchor (<a>) elements. Use onClick event handlers on non-interactive wrapper divs rather than nesting a button inside a link.
- If using Wix Blocks or a custom widget, open the widget in Wix Blocks and restructure the element hierarchy so interactive children are siblings of — not descendants of — other interactive elements.
- Publish and test keyboard navigation on the live site.
How to fix nested interactive on Squarespace
- In your Squarespace Admin go to Pages → (your page) → Edit, and identify the section/block containing the nested interactive element.
- For product blocks and summary blocks, Squarespace renders HTML you cannot edit directly in the standard editor. Go to Website → Pages → (any page) → Edit → click the block → Design to check available layout options that may reduce nesting.
- For custom code blocks or custom CSS, go to Website → Design → Custom CSS or insert a Code Block to inject corrective markup. You can use CSS to reorder or overlay elements to remove the visual need for a nesting pattern.
- For broader structural fixes (e.g. navigation), go to Design → Custom Code → Header (or Footer) Code Injection and add a small JavaScript snippet that removes the tabindex or restructures the DOM after page load — note this is a workaround, not a true fix.
- If your template supports Developer Mode (older Squarespace 7.0 templates), enable it and edit the .item block files directly to restructure the HTML.
- Test keyboard navigation after saving.
How to fix nested interactive on Webflow
- Open your project in the Webflow Designer.
- In the Navigator panel (left sidebar), locate the offending component — typically a Collection List Item, a Link Block, or a Card component that contains a Button or another Link Block inside it.
- Select the outer interactive wrapper (e.g. a Link Block). In the Settings panel (right sidebar) check its tag/element type.
- Change the outer wrapper from a Link Block to a Div Block: right-click the element in the Navigator → 'Change tag' is not directly available, so instead: (a) add a new Div Block at the same level, (b) move all children into it, (c) delete the old Link Block, then (d) add the product title link as a separate Link element inside the new Div.
- Ensure the Add to Cart button (from the Webflow Ecommerce Add to Cart component) and the title Link are direct children of the new Div, not nested inside each other.
- Publish and test keyboard tab order in a browser.
How to fix nested interactive on Adobe Commerce (Magento)
- Identify the template file rendering the offending component. Product cards are typically in app/design/frontend/<Vendor>/<Theme>/Magento_Catalog/templates/product/list.phtml or a widget template.
- Copy the relevant .phtml file into your custom theme directory (following Magento's template override hierarchy) if you have not already.
- Open the file and locate the wrapping <a> element (usually wrapping the product image and name) that also contains a button or another link (e.g. Add to Cart, Wishlist).
- Refactor: change the outer wrapper to a <div>, give the product name/image its own <a href>, and ensure all action buttons (Add to Cart, Compare, Wishlist) are sibling elements of that link, not children.
- Run bin/magento cache:clean and bin/magento setup:static-content:deploy (if in production mode) to clear compiled templates.
- Test keyboard navigation on the category page in a browser.
How to fix nested interactive on Magento Open Source
- Follow the same template-override process as Adobe Commerce: copy the relevant .phtml file (e.g. vendor/magento/module-catalog/view/frontend/templates/product/list.phtml) into your theme at app/design/frontend/<Vendor>/<Theme>/Magento_Catalog/templates/product/list.phtml.
- Edit the copied template to replace any wrapping interactive element (e.g. <a> around the whole card) with a <div>, and ensure product title links and action buttons are siblings.
- Clear the Magento cache: bin/magento cache:clean.
- Test keyboard tab order on the frontend.
How to fix nested interactive on PrestaShop
- In your PrestaShop back office, go to Design → Theme & Logo → (your theme) and note the active theme name.
- Via FTP/SFTP, navigate to themes/<your-theme>/templates/catalog/_partials/miniatures/product.tpl — this is the product card template.
- Open the file and find the wrapping <a> or interactive element that contains nested focusable children (e.g. a quick-view button or Add to Cart inside a link).
- Restructure using the sibling pattern: use a non-interactive <div> as the card wrapper, and place the product link and action buttons as direct siblings.
- Clear the PrestaShop cache: Advanced Parameters → Performance → Clear cache.
- Test keyboard navigation on the category page.
Does your site have this issue?
Run a free SEOLZ audit to find nested interactive — and every other issue — across your whole site in minutes.
Scan my site freeFrequently asked questions
What is Nested interactive?
WCAG Success Criterion 4.1.2 requires that every interactive component on a page has a clear name, role, and value that assistive technologies can understand. A "nested interactive" violation means a clickable or focusable element — like a button, link, or input — contains another focusable element inside it. For example, a product card that is wrapped in a `<a>` tag but also contains a separate "Add to Cart" `<button>` inside it, or a `<button>` that wraps a `<label>` and an `<input>`. HTML does not allow interactive elements to be nested inside other interactive elements — it is invalid markup that breaks predictable keyboard and screen-reader behavior.
Why does nested interactive matter?
Keyboard-only users and screen-reader users (blind shoppers, people with motor disabilities) navigate your store by tabbing through focusable elements. When interactive elements are nested, the browser renders the structure unpredictably: focus may skip the inner element, become trapped, or announce confusing information (e.g. reading an entire product card as one gigantic link). This directly prevents some customers from adding items to their cart, completing checkout, or using navigation menus — losing you real revenue. In many jurisdictions (US ADA, EU EAA, UK PSBAR) inaccessible ecommerce sites expose businesses to legal complaints and lawsuits. Fixing nested interactive elements is one of the most impactful keyboard-accessibility improvements you can make.
How do I fix nested interactive?
Remove or restructure focusable elements nested inside interactive controls so that no interactive element contains another focusable child.
Authoritative references
- How to fix this specific rule — Deque/axe (rule reference)
- WCAG 2 overview — W3C WAI
- ARIA basics — MDN