Product Card
A product card is a specialized <article> that displays a product's image, name, and price together with optional description, badges, and action buttons, presenting one product as a self-contained landmark for catalogs, search results, and recommendation strips.
Use it for e-commerce listings, marketplace browse pages, recommendation modules, and any context where products are presented in a uniform card layout.
Implementation Notes
- Renders an
<article>withclass="product-card"so each card is a discrete landmark aria-labeldefaults to the product name; consumers may override vialabel- Optional
imageUrlrenders an<img class="product-card-image" alt={imageAlt}> - The header contains
<h3 class="product-card-name">{name}</h3>and<p class="product-card-price">{price}</p> - Children render after the header for description, ratings, action buttons, etc.
- Price text is consumer-formatted — the component does not perform currency localization
Props
name: string (required) -- product nameprice: string (required) -- pre-formatted price textimageUrl: string (optional) -- product image srcimageAlt: string (optional) -- product image alt textlabel: string (optional) -- aria-label override (defaults toname)children: slot -- additional content (description, actions)...restProps: any additional HTML attributes
Usage
Basic product card:
<ProductCard
name="Premium notebook"
price="$19.99"
imageUrl="/img/notebook.jpg"
imageAlt="Premium notebook with embossed cover"
/>
Product card with description and actions:
<ProductCard
name="Premium notebook"
price="$19.99"
imageUrl="/img/notebook.jpg"
imageAlt="Premium notebook with embossed cover"
>
<p>180 pages, dot-grid, hardcover.</p>
<FlexStack direction="row">
<Button>Add to cart</Button>
<IconButton label="Save for later">♡</IconButton>
</FlexStack>
</ProductCard>
Keyboard Interactions
- None on the card itself.
- Focusable controls inside the card (e.g., add-to-cart button) follow their own keyboard behavior.
ARIA
<article>provides an implicit landmarkaria-labeldefaults tonameand may be overridden bylabel- The image's
alttext is the consumer's responsibility (pass viaimageAlt)
When to Use
- Use to present a single product in catalogs, search results, recommendation strips, and shopping cart summaries.
- Use when products are displayed in a uniform layout and each item has an image, name, and price.
- Use as a child of Grid or Masonry for product listings.
When Not to Use
- Do not use for non-product content (use Card or Tile).
- Do not use as a navigation tile (use Tile or a labeled link).
- Do not omit
imageAltwhen an image is provided — alt text is required for non-decorative images.
Headless
Provides only the semantic structure (article, headings, image, slot for extras). Layout, sizing, badge styling, hover states, and any visual treatment are the consumer's responsibility.
Styles
Consumer CSS targets .product-card, .product-card-image, .product-card-header, .product-card-name, and .product-card-price for visual styling.
Testing
- Verify the component renders an
<article>element with classproduct-card - Verify
aria-labeldefaults tonameand is overridable bylabel - Verify the image renders only when
imageUrlis provided, with the suppliedalt - Verify the name renders inside
<h3 class="product-card-name"> - Verify the price renders inside
<p class="product-card-price"> - Verify children content is rendered after the header
Domain Knowledge
- Pre-format
priceto include currency symbol, thousands separators, and decimal places appropriate to the user's locale. - For sale or strike-through pricing, pass formatted text (e.g.,
<del>$24.99</del> $19.99) via the slot or include it inprice.
Advice
- Designers: Maintain a consistent aspect ratio for product images across cards. Keep the price visually prominent and the action button reachable on small screens.
- Developers: Always supply
imageAlt. For decorative product photos that duplicate the name, an emptyalt=""is acceptable, but if the image conveys information not in the name, write descriptive alt text.
Related components
card— a grouped content container with header, body, and footer areasfeature-card— a large content card with a prominent image positioned alongside or above the text
References
- MDN article element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article
- WCAG 1.1.1 Non-text Content: https://www.w3.org/WAI/WCAG22/Understanding/non-text-content