Skip to main content

Overview

The product-card snippet renders a product in a card layout with customizable children blocks. It’s used throughout the theme in product grids, featured product sections, and collection pages. File Location: snippets/product-card.liquid

Parameters

product
object
required
The Shopify product object to display. Can be null for placeholder rendering.
children
string
required
HTML content to render inside the product card (typically captured from blocks).
block
object
The block object containing settings for styling and configuration.
product_card_gap
number
Gap between product card children in pixels. Overrides block settings if provided.Default: Uses block.settings.product_card_gap

Usage

Basic Example

{% liquid
  assign product = block.settings.product
%}

{% capture children %}
  {% content_for 'blocks', closest.product: product %}
{% endcapture %}

{% render 'product-card', 
  children: children, 
  product: product, 
  block: block 
%}

With Custom Gap

{% render 'product-card',
  product: product,
  children: children,
  block: block,
  product_card_gap: 24
%}

With Child Blocks

{% capture children %}
  {% # Product card gallery %}
  {% render 'card-gallery', product: product %}
  
  {% # Product title %}
  <h3 class="product-card__title">
    {{ product.title }}
  </h3>
  
  {% # Product price %}
  {% render 'price', product_resource: product %}
{% endcapture %}

{% render 'product-card',
  product: product,
  children: children,
  block: block
%}

Features

View Transitions

When settings.transition_to_main_product is enabled, the product card supports smooth view transitions to product pages:
product-card.liquid
data-product-transition="true"
data-featured-media-url="{{ featured_media_url }}"
on:click="/handleViewTransition"

Quick Add Integration

The snippet automatically configures quick add functionality based on theme settings:
product-card.liquid
assign has_quick_add = false
if settings.quick_add and product.available
  assign has_quick_add = true
endif

assign has_mobile_quick_add = false
if has_quick_add and settings.mobile_quick_add
  assign has_mobile_quick_add = true
endif
These values set CSS custom properties:
--quick-add-display: {% if has_quick_add %}flex{% else %}none{% endif %};
--quick-add-mobile-display: {% if has_mobile_quick_add %}flex{% else %}none{% endif %};

Placeholder Support

The snippet automatically detects when it should render a placeholder:
product-card.liquid
assign onboarding = false
if product.id == empty or product == blank
  assign onboarding = true
endif
Placeholder cards render without links and include data-placeholder="true".

Styling

The product card applies several style utilities:

Layout Classes

  • layout-panel-flex - Flexbox container
  • layout-panel-flex--column - Vertical layout
  • product-grid__card - Grid-specific styling

Utility Classes

  • spacing-style - Applies padding from block settings
  • border-style - Border styling from block settings
  • gap-style - Gap between children
  • size-style - Width/height dimensions

Color Schemes

color-{{ block_settings.color_scheme }}
Only applied when block_settings.inherit_color_scheme is false.

Custom Properties

The snippet generates CSS custom properties for responsive padding:
{% if block_settings.padding-inline-start > 0 %}
  --zoom-out-padding-inline-start: min(var(--padding-xs), {{ block_settings.padding-inline-start | times: 0.7}}px);
{% endif %}
This creates reduced padding for hover/zoom states (70% of original).

Block Settings

When used in a block context, the snippet reads settings from block.settings:
{
  "product_card_gap": 16,
  "inherit_color_scheme": true,
  "color_scheme": "scheme-1",
  "width": "fill",
  "border": "none",
  "border_width": 1,
  "border_radius": 0,
  "padding-block-start": 0,
  "padding-block-end": 0,
  "padding-inline-start": 0,
  "padding-inline-end": 0
}

Common Child Blocks

Product cards typically contain these child blocks:
<h3 class="product-card__title">
  <a href="{{ product.url }}">
    {{ product.title }}
  </a>
</h3>
The product name, typically rendered as a heading.
{% render 'price', 
  product_resource: product,
  show_unit_price: false,
  show_sale_price_first: true 
%}
Product pricing with sale price and compare-at price support.
{% render 'variant-swatches',
  product: product,
  block: swatches_block
%}
Color or image swatches for variant selection.
{% render 'quick-add',
  product: product,
  block: quick_add_block
%}
Quick add to cart functionality without navigating to product page.

Accessibility

The product card includes a visually hidden link for screen readers:
product-card.liquid
<a
  id="{{ product_card_id | md5 }}"
  href="{{ variant_to_link.url }}"
  class="product-card__link"
  ref="productCardLink"
>
  <span class="visually-hidden">
    {{ product.title }}
  </span>
</a>
This ensures keyboard navigation and screen reader users can access the product link.

Examples

{%- for product in collection.products -%}
  {% capture children %}
    {% render 'card-gallery', product: product %}
    <h3>{{ product.title }}</h3>
    {% render 'price', product_resource: product %}
  {% endcapture %}
  
  {% render 'product-card',
    product: product,
    children: children,
    block: block
  %}
{%- endfor -%}
  • Price - Product pricing display
  • card-gallery.liquid - Product image gallery for cards
  • variant-swatches.liquid - Variant selection UI
  • quick-add.liquid - Quick add to cart functionality

Build docs developers (and LLMs) love