NORTH JS TECH
Skip to content
North Js Tech

Product Cards

What it is / what it's for

A product card is the compact tile that represents a single product in a list — its image, title, price, and an "add" button. You see product cards everywhere shoppers browse multiple products: collection pages, homepage product sliders, search results, "you may also like" recommendations, recently‑viewed, and more.

All of those places use the same card, so a change to the card's look or behaviour updates it consistently across the whole store.

The card can:

  • Show a second image on hover, or run a mini image slider on the tile.
  • Show sale / sold‑out / new badges.
  • Let shoppers pick a variant (e.g. colour) right on the card, with the price and image updating instantly.
  • Add to cart directly, or open a quick‑view popup of the product — without leaving the page.
  • Display in different styles: vertical, horizontal, overlay (text over the image), or a "creative" shaped card.
product cards cutline shopify theme

Where it lives

PurposeFile
Main card (the "orchestrator")`snippets/card-product.liquid`
Card image area (hover image, slider, badges, in‑image button)`snippets/card-product-media.liquid`
Card text area (reorderable rows)`snippets/card-product-content.liquid`
Overlay‑style action buttons over the image`snippets/card-product-overlay-chrome.liquid`
The add / quick‑view button`snippets/card-add-button.liquid`
Behaviour (instant variant updates)`assets/product-card.js` (source: `src/scripts/product-card.ts`)
Styling`assets/card-product.css` (source: `src/styles/scss/snippets/card-product.scss`)
Behind‑the‑scenes endpoint for variant updates`sections/product-card-ajax.liquid`

What it looks like / key parts

A typical card, top to bottom:

  1. Image area — the product photo, optional hover/second image or slider, and any badges (sale, sold out, new).
  2. Add / quick‑view button — can sit over the image or below the text, depending on settings.
  3. Text area — vendor (brand), title, price, optional variant options, rating stars, SKU, stock status, or custom text. These rows can be reordered.

Settings you can change

Where: Product card settings are theme‑wide (they apply to every card in the store). Find them in the Shopify theme editor under Theme settings → Product cards and Theme settings → Product options. (They are not edited per‑section.)

Card appearance

SettingWhat it does
**Card style**Choose the overall layout: *Vertical* (image on top, text below), *Horizontal* (image beside text), *Overlay* (text on top of the image), or *Creative* (a shaped/clipped card).
**Padding**How much space around the card content: *Compact*, *Default*, or *Spacious*.
**Image fit**Whether images *Cover* the frame (cropped to fill) or *Contain* (whole image shown, may letterbox).
**Image hover**What happens on hover — e.g. fade to a second product image.
**Media mode***Single* image, *Hover* (primary + second image), or *Slider* (a mini carousel of the product's images on the tile).
**Slider arrows / pagination**For slider mode: show arrows and the dots/lines/fraction indicator.
**Sold‑out treatment**How unavailable products look: normal, *grayscale*, or *dimmed*.
**Creative shape**For the creative style: the shape applied to the card.

The add button

SettingWhat it does
**Button position (desktop & mobile)**Place the add button *inside the image* or *below the content*. Desktop and mobile can differ.
**Inside‑media button style**When the button sits on the image: show it as an icon only, or with text.

Variant options on the card

SettingWhat it does
**Show product options** (`product_options_enable`)Show variant pickers (e.g. colour/size) directly on the card so shoppers can switch without opening the product.
**Visible option labels** (`product_options_visible_labels`)Instead of showing all options, show only specific ones (e.g. only "Color").
**Picker type / sizes / colours**Whether options appear as swatches, buttons, or a dropdown, and how they're sized and coloured.

Tip

If a product has multiple variants but options are not shown on the card, the card automatically uses a quick‑view popup for adding to cart (so the shopper can choose a variant in the popup).

Reorderable text rows (card blocks)

The card's text area is made of blocks you can add, remove, and reorder in the theme editor (within the section that displays the cards). Available rows:

Row (block)Shows
**Vendor**The brand / vendor name.
**Title**The product name (links to the product).
**Price**Price, sale price, and "From" price where relevant.
**Options**On‑card variant pickers (swatches/buttons/dropdown).
**Add button**The add‑to‑cart / quick‑view button.
**Description**A short product description (trimmed to a few lines).
**SKU**The product/variant SKU code.
**Rating**Star rating (read from product review metafields).
**Inventory**Stock status message (e.g. "Low stock").
**Custom text**Free text, or text pulled from a product metafield.

What it depends on

The card pulls in these shared snippets (documented in [Shared Product Components.md](./Shared%20Product%20Components.md)):

  • price — the price display
  • product-options (and option-group, swatch) — variant pickers
  • badge — sale / sold‑out / new labels
  • inventory — stock status
  • product-title — the title text
  • card-add-button → which renders either product-form (direct add to cart) or quick-add-modal (quick view)
  • image, placeholder-image, loading-spinner — images and loading states

It loads:

  • CSS: assets/card-product.css
  • JavaScript: assets/product-card.js — but only on the real page, not inside the behind‑the‑scenes fragment used for variant updates (this avoids loading the script twice).

How it connects to the rest of the theme

The card is rendered by many sections. The most important:

SectionWhere shoppers see it
`sections/main-collection-product-grid.liquid`The main collection page grid
`sections/featured-collection.liquid`Homepage / page product sliders and grids
`sections/main-search.liquid`Search results
`sections/product-recommendations.liquid`"You may also like"
`sections/recently-viewed-products.liquid`Recently viewed
`sections/product-spotlight.liquid`, `favorite-collection.liquid`, `category-product-tabs.liquid`Various product showcases
`snippets/mega-menu-tabbed-columns-slider.liquid`Product tiles inside the mega‑menu

When a shopper changes a variant on a card, the card asks the server for an up‑to‑date copy of itself via sections/product-card-ajax.liquid and swaps in the new price, image, stock, and button state.

Product data it uses

  • Variants — to show the right price/image and to add the chosen variant to the cart.
  • Images / media — main image, optional second (hover) image, or the full set for slider mode; can switch to the selected variant's image.
  • Availability & inventory — for sold‑out styling and stock messages.
  • Price & compare‑at price — for regular, sale, and "From" pricing.
  • Metafields — review rating/score for the star‑rating row, and any metafield used by a "custom text" row.

Customization points & important notes

  • Most card appearance is global. Because card settings live in Theme settings → Product cards, changing them updates cards everywhere at once. That's usually what you want; just be aware it's not per‑section.
  • Reordering rows is done per the section that displays the cards (its card blocks), so different sections can show different rows.
  • Overlay style hides the vendor and uses an action stack over the image; some other settings don't apply to it.
  • Editing styles: change src/styles/scss/snippets/card-product.scss, not the compiled assets/card-product.css (it's overwritten by the build).
  • Limitation: the card itself doesn't have its own settings panel; it inherits from theme‑wide settings plus the reorderable blocks of the section showing it.

Behind the scenes (for developers)

Orchestration. snippets/card-product.liquid computes display state from theme settings — card-product.liquid:17-103 (padding, sold‑out treatment, image fit, hover mode, multi‑variant detection, card_options_visible, card_show_quick_view, has_card_blocks) and the per‑breakpoint add‑button placement engine (card-product.liquid:105-194). The canonical form id is quick-add-<section_id>-<product.id>[-<card_index>] (card-product.liquid:50-56).

Custom element. The root is <product-card> (card-product.liquid:197-206) carrying data-product-url, data-media-mode, and (when variant images are enabled) data-variant-media-id. Behaviour is in assets/product-card.js (compiled from src/scripts/product-card.ts).

AJAX variant update flow. assets/product-card.js:

  1. The card listens for the product-options:change event emitted by assets/product-options.js.
  2. On change it fetches \<productUrl\>?section_id=product-card-ajax&option_values=\<ids\> (Shopify Section Rendering API → sections/product-card-ajax.liquid). Results are cached per productUrl::ids; an in‑flight request is aborted if a newer change arrives.
  3. applyVariantHtml() surgically swaps the live DOM: replaces product-price, swaps the primary image children (or navigates the Splide slider to the variant's media via data-variant-media-id), replaces .card-product__badge, syncs the submit button + hidden js-product-form-variant-id, SKU (js-card-sku), inventory (js-card-inventory), toggles card-product--soldout-grayscale/-dim, and dispatches product-card:variant-change.
  4. If the variant combination doesn't exist, setUnavailable() disables the form and shows window.variantStrings.unavailable.

AJAX fragment. The fragment is produced by the ajax: true branch of card-product.liquid (the flat, non‑block content layout). That branch deliberately omits the <script> tag (card-product.liquid:372) so the JS isn't re‑injected when the fragment is swapped in.

Endpoint note. The live endpoint is the section sections/product-card-ajax.liquid (section_id=product-card-ajax). The separate file templates/product.product-ajax-do-not-select-or-delete.liquid renders the same card with section_id: 'ajax' and is not the path the card JS calls.

Sub‑snippets:

  • card-product-media.liquid — image/hover/slider, primary‑image marker js-card-primary-image, variant image swap, badges, and the in‑media add button instances.
  • card-product-content.liquid — iterates the card blocks in customizer order; rating block reads card_product.metafields.reviews.rating and reviews.rating_count; custom‑text block reads a metafield or literal text; each block emits block.shopify_attributes.
  • card-product-overlay-chrome.liquid — overlay‑style action stack (only for overlay style, non‑horizontal).
  • card-add-button.liquid — quick‑view branch (renders quick-add-modal, button carries js-quick-add-trigger + data-product-url) vs add‑to‑cart branch (renders product-form with context: 'card').

Styling. src/styles/scss/snippets/card-product.scssassets/card-product.css. Key classes: .card-product (+ --horizontal, --shaped, --soldout-grayscale/-dim), &__media (hover zoom on .group:hover & img), slider chrome (&__media--slider, &__slider-arrow, &__pagination-fraction), &__badge, &__icon, &__content (alignment via --card-text-align/--card-content-align), &__title, &__button, &__rating, &__description.

Naming gotcha: the card markup uses the BEM prefix card-product__*, while the form/quick‑add controls use product-card__*. There is no snippets/product-card.liquid — the snippet is card-product.liquid; only the custom element, JS asset, and some classes use the product-card name.

Last updated July 4, 2026

Let's talk