Skip to content

component-product-price Snippet

snippets/component-product-price.liquid renders a product's price block including regular price, sale price, compare-at price, unit price, and optional sale/sold-out badges. It supports volume pricing messaging, variant-based pricing, and currency code display. The component handles complex pricing scenarios including products with varying prices and quantity-based pricing breaks.


What It Does

  • Renders product or variant prices with proper formatting.
  • Displays regular and sale prices with compare-at price strikethrough.
  • Shows unit pricing (price per unit of measurement).
  • Supports volume pricing with price range display.
  • Displays optional "Sale" and "Sold Out" badges.
  • Handles currency code display when enabled.
  • Provides accessible price labels for screen readers.
  • Applies dynamic CSS classes based on price state.

Parameters

ParameterTypeDefaultDescription
productobjectoptionalProduct object to render prices for.
placeholderbooleanoptionalRender placeholder pricing when no product.
use_variantbooleanoptionalUse selected/first variant instead of product-level pricing.
show_badgesbooleanoptionalShow "Sale" and "Sold Out" badges.
price_classstringoptionalExtra CSS class to append to price wrapper.
show_compare_at_pricebooleanoptionalShow compare-at price when applicable (for volume pricing).

Dependencies & Assets

TypeFiles / Components
CSSExternal stylesheet (likely component-product-price.css)
JavaScriptNone required
Shopify Filtersmoney, money_with_currency, money_without_currency
DataRequires product object with pricing properties, settings.currency_code_enabled
  • No external JavaScript required - all functionality handled by Liquid.
  • External CSS handles all price styling and badge display.
  • Shopify money filters handle currency formatting.

Dynamic Styles

The snippet does not include inline styles. All styling is handled by external CSS files. However, the component uses dynamic CSS classes based on price state:

liquid
class="
  price
  {%- if price_class %} {{ price_class }}{% endif -%}
  {%- if available == false %} price--sold-out{% endif -%}
  {%- if compare_at_price > price and product.quantity_price_breaks_configured? != true %} price--on-sale{% endif -%}
  {%- if compare_at_price > price and product.quantity_price_breaks_configured? %} volume-pricing--sale-badge{% endif -%}
  {%- if product.price_varies == false and product.compare_at_price_varies %} price--no-compare{% endif -%}
  {%- if show_badges %} price--show-badge{% endif -%}
"
  • Dynamic classes: Price wrapper classes change based on:
    • Custom class (price_class parameter)
    • Sold out state
    • Sale state
    • Volume pricing state
    • Price variation state
    • Badge display state

Markup Structure

liquid
<div class="price [dynamic classes]">
  <div class="price__container">
    <div class="price__regular">
      <!-- Regular price display -->
    </div>
    <div class="price__sale">
      <!-- Sale price display -->
    </div>
    <small class="unit-price">
      <!-- Unit price display -->
    </small>
  </div>
  {%- if show_badges -%}
    <!-- Sale and Sold Out badges -->
  {%- endif -%}
</div>
  • Two price displays: price__regular and price__sale - CSS controls which is visible.
  • Unit price: Displayed in <small> element when unit pricing available.
  • Badges: Optional sale and sold-out badges.

Regular Price Display

liquid
<div class="price__regular">
  {%- if product.quantity_price_breaks_configured? -%}
    <!-- Volume pricing range -->
  {%- else -%}
    <!-- Standard price -->
  {%- endif -%}
</div>
  • Volume pricing: Shows price range when quantity breaks configured.
  • Standard pricing: Shows single price otherwise.

Sale Price Display

liquid
<div class="price__sale">
  {%- unless product.price_varies == false and product.compare_at_price_varies %}
    <span>
      <s class="price-item price-item--regular">
        {{ compare_at_price | money }}
      </s>
    </span>
  {%- endunless -%}
  <span class="price-item price-item--sale price-item--last">
    {{ money_price }}
  </span>
</div>
  • Compare-at price: Strikethrough price shown when on sale.
  • Sale price: Current sale price displayed.
  • Conditional compare-at: Compare-at price hidden in certain variation scenarios.

Unit Price Display

liquid
<small class="unit-price caption{% if product.selected_or_first_available_variant.unit_price_measurement == nil %} hidden{% endif %}">
  <span class="visually-hidden">{{ 'products.product.price.unit_price' | t }}</span>
  <span class="price-item price-item--last">
    <span>{{- product.selected_or_first_available_variant.unit_price | money -}}</span>
    <span aria-hidden="true">/</span>
    <span class="visually-hidden">&nbsp;{{ 'accessibility.unit_price_separator' | t }}&nbsp;</span>
    <span>
      {%- if product.selected_or_first_available_variant.unit_price_measurement.reference_value != 1 -%}
        {{- product.selected_or_first_available_variant.unit_price_measurement.reference_value -}}
      {%- endif -%}
      {{ product.selected_or_first_available_variant.unit_price_measurement.reference_unit }}
    </span>
  </span>
</small>
  • Conditional display: Hidden when unit pricing not available.
  • Accessible format: Includes visually hidden labels and separator.
  • Reference value: Shows measurement value if not 1 (e.g., "100" in "100ml").

Badges

liquid
{%- if show_badges -%}
  <span class="badge price__badge-sale">
    {{ 'products.product.on_sale' | t }}
  </span>
  <span class="badge price__badge-sold-out">
    {{ 'products.product.sold_out' | t }}
  </span>
{%- endif -%}
  • Sale badge: Shows "On Sale" text.
  • Sold out badge: Shows "Sold Out" text.
  • CSS control: CSS controls which badge is visible based on state.

Behavior

  • Price calculation: Calculates prices based on product or variant (controlled by use_variant).
  • Currency formatting: Formats prices using Shopify money filters.
  • Currency code: Includes currency code when settings.currency_code_enabled is true.
  • Price variation: Handles products with varying prices across variants.
  • Volume pricing: Displays price range for quantity-based pricing.
  • Sale detection: Detects sale state by comparing price to compare-at price.
  • Badge visibility: CSS controls badge visibility based on sale/sold-out state.
  • Accessibility: Includes visually hidden labels for screen readers.

Usage Example

Basic usage:

liquid
{% render 'component-product-price', product: product %}

With variant pricing:

liquid
{% render 'component-product-price',
  product: product,
  use_variant: true
%}

With badges:

liquid
{% render 'component-product-price',
  product: product,
  show_badges: true
%}

With custom class:

liquid
{% render 'component-product-price',
  product: product,
  price_class: 'product-card__price'
%}

Typically used in:

  • Product pages (sections/product.liquid)
  • Product cards (snippets/component-product-card.liquid)
  • Collection pages
  • Search results
  • Any component displaying product pricing

Implementation Notes

  1. Target selection: Component selects pricing target based on parameters:

    • use_variant: Uses product.selected_or_first_available_variant
    • placeholder: Uses null (renders placeholder)
    • Otherwise: Uses product object
  2. Price calculation: Prices calculated from target object:

    • compare_at_price: From target's compare-at price
    • price: From target's price (defaults to 1999 if null)
    • price_min/price_max: From product's price range
    • available: From target's availability (defaults to false)
  3. Currency formatting: Prices formatted using:

    • money: Standard money format
    • money_with_currency: Includes currency code (when enabled)
    • money_without_currency: Currency code only (for structured data)
  4. Currency code setting: Checks settings.currency_code_enabled to determine format.

  5. Price variation handling: When target == product and product.price_varies, uses translation with "from" prefix.

  6. Volume pricing: Detects product.quantity_price_breaks_configured? to show price range instead of single price.

  7. Compare-at price display: Compare-at price shown when:

    • show_compare_at_price is true
    • compare_at_price exists
    • Not in certain variation scenarios
  8. Price display logic: Two price divs (price__regular and price__sale) - CSS controls visibility based on sale state.

  9. Sale detection: Sale detected when compare_at_price > price.

  10. CSS class system: Dynamic classes applied based on:

    • price--sold-out: When product unavailable
    • price--on-sale: When on sale (non-volume pricing)
    • volume-pricing--sale-badge: When on sale with volume pricing
    • price--no-compare: When price doesn't vary but compare-at does
    • price--show-badge: When badges enabled
  11. Accessibility features:

    • visually-hidden labels for price types
    • visually-hidden separator for unit price
    • aria-hidden="true" on decorative separator
    • Semantic HTML structure
  12. Translation keys: Uses translation keys from locales/en.default.json:

    • products.product.price.regular_price
    • products.product.price.sale_price
    • products.product.price.unit_price
    • products.product.price.from_price_html
    • products.product.volume_pricing.price_range
    • products.product.on_sale
    • products.product.sold_out
    • accessibility.unit_price_separator
  13. Unit price calculation: Unit price calculated from variant's unit_price and unit_price_measurement.

  14. Unit price display: Unit price hidden when unit_price_measurement == nil.

  15. Reference value: Unit price reference value only shown if not 1 (e.g., "100" in "$1.00 / 100ml").

  16. Badge display: Badges only render when show_badges is true, but CSS controls which is visible.

  17. Placeholder support: Component can render placeholder pricing when placeholder is true and target is null.

  18. Price item classes: Price elements use classes:

    • price-item: Base price item class
    • price-item--regular: Regular/compare-at price
    • price-item--sale: Sale price
    • price-item--last: Last price item in group
  19. Strikethrough price: Compare-at price uses <s> tag for strikethrough styling.

  20. Conditional rendering: Component only renders when target != null or placeholder != null.

  21. Price range translation: Volume pricing uses translation with minimum and maximum variables.

  22. From price translation: Varying prices use translation with price variable for "from" prefix.

  23. Currency code conditional: Currency code included when settings.currency_code_enabled is true.

  24. Price variation scenarios: Component handles complex scenarios:

    • Price varies, compare-at varies
    • Price doesn't vary, compare-at varies
    • Price varies, compare-at doesn't vary
    • Neither varies
  25. Volume pricing compare-at: Compare-at price shown in volume pricing when show_compare_at_price is true.

  26. No compare-at in variations: Compare-at price hidden when product.price_varies == false and product.compare_at_price_varies.

  27. Unit price measurement: Unit price uses variant's unit_price_measurement for reference value and unit.

  28. Badge CSS control: Badges always rendered but CSS controls visibility based on sale/sold-out state.

  29. Sold out class: price--sold-out class applied when available == false.

  30. Sale class logic: Sale class depends on volume pricing configuration:

    • price--on-sale: When not volume pricing
    • volume-pricing--sale-badge: When volume pricing
  31. Price container: All price displays wrapped in price__container div.

  32. Regular price display: Regular price shown when not on sale or in volume pricing mode.

  33. Sale price display: Sale price shown when on sale (compare-at > price).

  34. Unit price positioning: Unit price displayed after regular/sale prices in <small> element.

  35. Badge positioning: Badges displayed after price container.

  36. Price formatting: All prices formatted using Shopify money filters for proper currency display.

  37. Default price: Price defaults to 1999 (in cents) if target price is null.

  38. Default availability: Availability defaults to false if target availability is null.

  39. Money variable assignment: Prices converted to money format early for reuse.

  40. Price min/max: Product price min/max used for volume pricing range.

  41. Target comparison: Component compares target == product to determine if using product-level pricing.

  42. Price varies check: Checks product.price_varies to determine if prices differ across variants.

  43. Compare-at varies check: Checks product.compare_at_price_varies for compare-at price variation.

  44. Quantity breaks check: Checks product.quantity_price_breaks_configured? for volume pricing.

  45. Unit price measurement check: Checks unit_price_measurement == nil to hide unit price.

  46. Reference value check: Only shows reference value if not 1.

  47. Currency code setting: Checks settings.currency_code_enabled for currency display.

  48. Translation interpolation: Uses translation variables for dynamic content:

    • from_price_html: price variable
    • volume_pricing.price_range: minimum, maximum variables
  49. Accessibility labels: All price types have visually hidden labels for screen readers.

  50. Semantic HTML: Uses semantic elements (<s> for strikethrough, <small> for unit price).