Utilities✨ Premium

Product Card

Product card in three sizes depending on the room it gets: compact, with a description from 220 px, then a row with a second button from 300 px.

CSS@containerE-commerce

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Utilities has 43 effects, including 3 free. Explore the category →

3 usage examples

Gresmoire ceramics — the bowl as a row in the showcase, the vase compact in “Recently viewed” — Product Card example 1

① Gresmoire ceramics — the bowl as a row in the showcase, the vase compact in “Recently viewed”

WhenOn the collection page the bowl card fills the main column and shows everything (description, two buttons). In the 172 px “Recently viewed” column the same card shrinks to visual, name, price and “Buy”.
WhyThe shop uses one component everywhere; the narrow column never gets squeezed text or a clipped button, because what does not fit is simply not shown.
SettingsTwo roots with name, price, description and pictogram replaced; visuals set with style="background-image:…" on .pdc-image. 172 px right-hand column.
Quenvarre page builder — widening the product block next to a text — Product Card example 2

② Quenvarre page builder — widening the product block next to a text

WhenThe merchant drags the handle between the product block and its text (or uses the arrow keys): the description appears at 220 px, then the card becomes a row and gains “Details” at 300 px. On load the width sweeps back and forth to show the steps.
WhyYou see at once which column width gives the full card, without previewing three screen sizes.
SettingsThe handle sets the width of the root's parent between 160 and 315 px (wired in <script data-scenes>); the dark card sits on the builder's light page with no other setting.
Talvérine live sale — the teapot card goes compact when the chat opens — Product Card example 3

③ Talvérine live sale — the teapot card goes compact when the chat opens

WhenDuring the stream, the card of the featured product is a row next to the vertical video. The viewer taps “Chat”: the message column opens, the product panel drops to about 170 px and the card keeps only what is needed to buy.
Why“Buy” stays visible and whole while people chat, with no second version of the card to maintain.
SettingsThe “Chat” button (aria-expanded) opens a 148 px column in the scene grid; the card reacts to its new width through its own rules.

How it works

The queried container is the .fx-0749-root element (container: pdc-card / inline-size, width: 100%). The .pdc-card starts as a column: a 90 px tall .pdc-image visual (indigo-to-violet gradient, tag pictogram), the name in an h4, the .pdc-price in light violet, then a single “Buy” button. The .pdc-desc description and the “Details” button are in the HTML but stay at display: none.

First step, @container pdc-card (min-width: 220px): the description shows up under the price. Second step, min-width: 300px: the card becomes a row, the visual turns into a 96 px column (at least 110 px tall), the buttons move to the bottom of the card (margin-top: auto) and “Details” appears next to “Buy”. Three shapes in all, measured at 170, 260 and 330 px of container width.

Both buttons are real <button type="button"> elements that do nothing on their own: hook them to your cart or product page (or swap them for <a> links). A button hidden with display: none also leaves the tab order, so the keyboard never lands on an invisible button.

Accessibility

  • Real buttons: “Buy” and “Details” are <button> elements, reachable with Tab (in Safari, depending on the macOS keyboard setting) and outlined in light violet on :focus-visible.
  • Contrast: white text on the #7c3aed button and the #a78bfa price on the dark background are both above 4.5:1.
  • Content that goes away: under 220 px the description is not displayed, so it is not read either. If it holds essential information (size, allergen…), keep it visible by removing the display: none from .pdc-desc.
  • Pictogram: the SVG has aria-hidden="true"; the product name in the h4 is enough to identify it.
  • Reduced motion: card, visual and button transitions are removed under prefers-reduced-motion: reduce.

Browser compatibility

Container queries and flexbox, nothing else. Measured in Chromium 151, Firefox 153 and WebKit 26.5: three shapes at the same widths, no overflow at 390 px, resizing one copy leaves the other alone.

Chrome 105+✓ Full (measured)
Firefox 110+✓ Full (measured)
Safari 16+✓ Full (measured in WebKit)
Edge 105+✓ Full
Mobile iOS 16+✓ Full
Android Chrome 105+✓ Full

Without container queries the card keeps its compact shape (visual, name, price, “Buy”): the description and “Details” stay hidden.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0749-root">
  <div class="pdc-card">
    <div class="pdc-image"><svg viewBox="0 0 24 24" aria-hidden="true">…</svg></div>
    <div class="pdc-info">
      <h4>Product name</h4>
      <span class="pdc-price">$29</span>
      <p class="pdc-desc">Short description</p>
      <div class="pdc-actions">
        <button type="button" class="pdc-btn pdc-btn--primary">Buy</button>
        <button type="button" class="pdc-btn pdc-btn--secondary">Details</button>
      </div>
    </div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Steps (CSS — @container pdc-card (min-width: 220px) and (min-width: 300px)) 220 px for the description, 300 px for the row With a long product name, move the row to 340 px; with a one-line description, the first step can go down to 200 px.
Visual (CSS or HTML — .pdc-image) #1e1b4b → #4c1d95 gradient + tag pictogram Set the product photo with style="background-image:url(…)" and remove the SVG; cover cropping is already in place.
Accent colour (CSS — .pdc-price and .pdc-btn--primary) #a78bfa / #7c3aed Replace both values with your brand colour, keeping 4.5:1 contrast with the button text.
Labels and actions (HTML — .pdc-btn) “Buy”, “Details”, no action Attach a click listener, or turn the tags into <a href="…"> while keeping the classes.
Visual width in the row (CSS — .pdc-image { width } in the 300 px step) 96 px, at least 110 px tall 130 px for very visual goods (clothing, decor), 72 px for a spare-parts catalogue.
Background (CSS — .fx-0749-root and .pdc-card) #0a0a0f and a 4 % white veil For a light shop: white background, dark heading, grey description.

FAQ

No, they are buttons with no action: the card only handles layout. Connect them to your cart code (addEventListener('click', …)) or make them links to your product page.
Below that, two buttons side by side would be too narrow for their labels. The second button is hidden (and taken out of the tab order) until the card has room to show it properly.
Yes, each root measures its own cell. With repeat(auto-fill, minmax(180px, 1fr)), the cards move from the compact to the full shape by themselves as the grid widens.