The pattern
The accessible product card pattern
Static image. Linked heading. Plain price. Separate action button. No nested or duplicate controls.
Anatomy
Every element earns its behavior.
Informative alt; no focus because it performs no action.
The single path to product details and first card tab stop.
Readable text, not a control.
A distinct action whose hidden suffix includes product context.
Harbor trail boot linkAdd to cart buttonStructure
Keep interactions as siblings.
A stretched card link must not contain the Add to cart button. Interactive elements cannot be nested, and a large overlay link can obscure text selection or other controls.
Fragile: entire card is a link
The nested button competes with its ancestor link. Names, events, focus styling, and hit targets become difficult to reason about.
<a href="/boot" class="card">
<h3>Harbor trail boot</h3>
<button>Add to cart</button> <!-- invalid nesting -->
</a>Robust: card contains sibling controls
The heading link navigates. The button acts. Their names and focus indicators remain independent.
<article>
<img src="boot.jpg" alt="Tan hiking boot…">
<h3><a href="/boot">Harbor trail boot</a></h3>
<p>$128</p>
<button>Add to cart <span class="sr-only">— Harbor trail boot</span></button>
</article>Quick test
Inspect one card before multiplying it.
- Confirm the image alt contributes useful product appearance and the image is not focusable.
- Confirm one heading link is the only path to product details.
- Confirm price remains readable text.
- Confirm Add to cart is a sibling button, not nested in a link.
- Press Tab: title link, then Add to cart.
- Confirm the button name includes both “Add to cart” and the product name.