Product Card — Free HTML CSS JS E-commerce Snippet

Product Card · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Colour swatch click: removes .active from all, adds to clicked swatch
.swatch.active ring via outline: 2px solid offset from swatch border
Heart wishlist toggle: .liked class fills SVG red via CSS fill/stroke
Add to Cart: textContent change + .added class + 1.5s setTimeout reset
Sale badge: position absolute overlay on .img-wrap with top/left
Star rating via Unicode ★ characters with amber colour
Original price strikethrough and sale price in red
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Product Card — Colour Swatches, Wishlist Toggle & Add to Cart Feedback

Screenshot of the Product Card snippet rendered live

A product card displays a product image, name, price, colour variants, rating, and an add-to-cart CTA in a compact format. It is the core unit of any e-commerce listing, marketplace, or product catalogue, and feeds the mini cart on add.

Colour swatches

Swatch divs have a data-colour attribute and a click listener that removes .active from all swatches then adds it to the clicked one. The CSS .swatch.active applies a ring via outline: 2px solid offset from the swatch border.

Wishlist toggle

The heart button calls toggleWish() which toggles .liked on the button — the same interaction as the standalone favorite button. CSS .wish.liked svg { fill: #ef4444; stroke: #ef4444 } makes the heart fill red when active. The state is purely visual — wire to an API or localStorage for persistence.

Add to Cart feedback

addToCart(btn) changes btn.textContent to "✓ Added!" and adds .added (green background). A setTimeout after 1.5s resets both. This prevents duplicate submissions and confirms the action without a modal.

Badge positioning

The .badge div uses position: absolute; top: 12px; left: 12px on the .img-wrap parent to overlay a "Sale" or "New" label on the product image.

The colour swatch selector

Each swatch button has a data-colour attribute. When clicked, updateSwatch(btn) reads btn.dataset.colour and applies it as the product image background colour: productImg.style.background = colour. The active swatch gets .active class which adds a ring indicator. This pattern demonstrates how to build a colour selector that updates visual state without navigating to a new page — the same interaction used on Apple, Nike, and most e-commerce product pages.

The wishlist toggle

The heart button toggles .liked class. In the liked state, the heart SVG switches from outline (fill="none") to filled (fill="currentColor"). The button colour changes from grey to red. This is the standard heart/save pattern. In a real product, the toggle triggers a PATCH request to your API to add or remove the product from the user's saved items.

Add to cart feedback state

Clicking "Add to Cart" shows a brief "Added!" text and green background for 1.5 seconds, then resets. This immediate visual confirmation is important for cart interactions — without it, users often click multiple times believing the first click failed.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to trace every click handler by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the swatch click handler's remove-then-add active class pattern works across a querySelectorAll loop, and why addToCart uses a setTimeout to revert the button's text and class instead of leaving it permanently changed. The same assistant can help optimize it, for example checking whether attaching a separate click listener to every individual swatch is the best approach versus a single delegated listener on the swatch container, or whether the wishlist heart's visual state should persist across a page reload. It's also useful for extending the effect: ask it to add a size selector alongside the color swatches using the same active-toggle pattern, persist the wishlist state to localStorage, or wire the swatch selection to actually swap the product image instead of just the ring indicator. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an e-commerce product card in plain HTML, CSS, and vanilla JavaScript with color swatches, a wishlist toggle, and add-to-cart feedback — no frameworks.

Requirements:
- A card showing a product image area (with a placeholder icon acceptable as the image), a floating wishlist heart button in one corner, a floating sale-percentage badge in another corner, a brand name, a product title, a star rating with a review count, a current price next to a struck-through original price, a row of color swatch circles, and an add-to-cart button.
- Clicking the wishlist heart button must toggle a "liked" visual state on that button — an outlined heart becomes a filled, colored heart (achieved through a CSS class toggle affecting fill and stroke), with no page reload.
- Clicking any color swatch must remove the active-state ring indicator from every other swatch and apply it only to the clicked one, so exactly one swatch is marked active at any time.
- Clicking the add-to-cart button must change its label text to a confirmation message (like a checkmark plus "Added!"), switch its background color to a distinct success color, and automatically revert both the label and the color back to their original state after roughly two seconds, without requiring another click.
- Style the active swatch's ring so it clearly stands out from unselected swatches, and make sure the sale badge and wishlist button are positioned as overlays on top of the image area using absolute positioning, not affecting the image's own layout.
- Keep every piece of behavior — swatch selection, wishlist toggle, and cart feedback — working independently, so clicking one does not interfere with or reset the state of the others.

Step by step

How to Use

  1. 1
    Interact with the cardClick the colour swatches, heart wishlist button, and Add to Cart button in the preview to see each interaction.
  2. 2
    Update product infoIn the HTML panel, change the product name, price, original price, and rating text.
  3. 3
    Change swatch coloursUpdate the background colour on each .swatch div inline style in the HTML panel.
  4. 4
    Replace the image placeholderReplace the .img-placeholder div with an <img> tag with object-fit: cover; width: 100%; height: 100%;.
  5. 5
    Change the badge textUpdate the .badge text in the HTML and its background colour in the CSS.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

E-commerce product listing grids
Use as the card unit in a product grid. Wire the swatch selection to filter images and the Add to Cart to your shopping cart state.
Marketplace and catalogue pages
Display products in a filterable grid. The colour swatches and wishlist make the card feel interactive rather than a static product thumbnail.
Learn swatch and toggle interaction patterns
The swatch click uses the same querySelectorAll remove-all-then-add pattern as tab bars. Edit the JS to understand the pattern.
Fashion and lifestyle product cards
Update swatch colours to seasonal palette options. Add a size selector row. The card layout scales to additional selection options.
Prototype checkout flow UI
Use the Add to Cart feedback animation to prototype the cart addition interaction before wiring a real cart state.
Product spotlight and featured items
Use the card with a "Featured" badge on a homepage product highlight. The compact card format shows all key purchase information.

Got questions?

Frequently Asked Questions

Each .swatch div has a click listener. On click, all swatches get .active removed via querySelectorAll, then .active is added to the clicked swatch. CSS .swatch.active applies a ring via outline: 2px solid at 2px offset.

In toggleWish(), save the state to localStorage: localStorage.setItem("wish-productId", btn.classList.contains("liked")). On page load, read the value and apply .liked if true.

In addToCart(btn), add your cart logic before the visual feedback: cart.push(productId) or fetch("/cart/add", { method: "POST", body: ... }). The visual feedback (textContent change, timeout reset) runs regardless.

Copy the swatch row structure and replace swatches with size buttons (XS, S, M, L, XL). Add .size-btn CSS for the button style and use the same querySelectorAll active pattern.

Replace <div class="img-placeholder">...</div> with <img src="url" alt="Product name" style="width:100%;height:100%;object-fit:cover;" />.

Yes. Click "JSX" for a React component. In React, manage selectedSwatch and isWished in useState. Pass product data as props. Wire the cart action to your cart context or Redux dispatch.