Next Commerce
Guides

Cart Summary

The Cart Summary displays the cart totals — subtotal, discounts, shipping, tax, and grand total — and updates automatically whenever the cart changes. Drop it anywhere on the page: a sidebar, a sticky footer, or an order review step.

What You're Building

  • A live price breakdown that re-renders when items are added, removed, or discounts change
  • Optional custom layout with your own markup
  • Conditional rows that appear only when relevant (e.g. a discount row only when a coupon is active)
  • An itemised line list with per-item pricing

Step 1: Minimal Setup

One attribute is all you need. The enhancer renders a built-in Subtotal / Discounts / Shipping / Total layout:

<div data-next-cart-summary></div>

The built-in template only shows the discount row when discounts are greater than zero, and omits the tax row when tax is zero. No extra configuration needed.

Step 2: Custom Template

Place a <template> inside the container to replace the default layout with your own markup. Use {variable} placeholders for dynamic values.

<div data-next-cart-summary>
  <template>
    <div class="summary-row">
      <span>Subtotal</span>
      <span>{subtotal}</span>
    </div>
    <div class="summary-row discount-row">
      <span>Discounts</span>
      <span>−{discounts}</span>
    </div>
    <div class="summary-row">
      <span>Shipping</span>
      <span>{shipping}</span>
    </div>
    <div class="summary-row total-row">
      <span>Total</span>
      <span>{total}</span>
    </div>
  </template>
</div>

Available Template Variables

VariableDescription
{subtotal}Subtotal before shipping and discounts
{total}Grand total
{shipping}Shipping cost (formatted, or "Free" when zero)
{shippingOriginal}Original shipping before any shipping discount (empty if none)
{tax}Tax amount
{discounts}Total discount amount (offers + vouchers combined)
{savings}Total savings: retail (compare-at minus price) + applied discounts
{compareTotal}Compare-at total (before savings)
{itemCount}Number of items in cart

Step 3: Conditional Rows with CSS Classes

The enhancer applies state classes to the container element. Use them to show or hide rows with CSS instead of writing JavaScript.

<div data-next-cart-summary>
  <template>
    <div class="row"><span>Subtotal</span><span>{subtotal}</span></div>
    <div class="row row-discounts"><span>Discounts</span><span>−{discounts}</span></div>
    <div class="row row-shipping-discount">
      <span>Shipping</span>
      <del>{shippingOriginal}</del>
      <span>{shipping}</span>
    </div>
    <div class="row row-shipping-free"><span>Shipping</span><span>Free</span></div>
    <div class="row row-tax"><span>Tax</span><span>{tax}</span></div>
    <div class="row row-total"><span>Total</span><span>{total}</span></div>
  </template>
</div>

<style>
  /* Hide these rows by default */
  .row-discounts,
  .row-shipping-discount,
  .row-tax { display: none }

  /* Show when state classes are present */
  .next-has-discounts .row-discounts    { display: flex }
  .next-has-shipping-discount .row-shipping-discount { display: flex }
  .next-has-shipping .row-shipping-free { display: none }
  .next-free-shipping .row-shipping-free { display: flex }
  .next-has-tax .row-tax               { display: flex }
</style>

State Classes Reference

ClassWhen applied
next-cart-emptyCart has no items
next-cart-has-itemsCart has one or more items
next-has-discountsDiscount amount > 0
next-no-discountsDiscount amount = 0
next-has-shippingShipping cost > 0
next-free-shippingShipping cost = 0
next-has-shipping-discountA shipping discount is applied
next-no-shipping-discountNo shipping discount
next-has-taxTax > 0
next-no-taxTax = 0
next-has-savingsRetail or discount savings available
next-no-savingsNo savings

Step 4: Itemised Line List

Show a breakdown of each cart line — useful for an order review section. Add a [data-summary-lines] container inside your template with a <template> child for the row markup.

<div data-next-cart-summary>
  <template>
    <ul class="line-items" data-summary-lines>
      <template>
        <li class="line-item">
          <img src="{line.image}" alt="{line.name}" />
          <div class="line-info">
            <strong>{line.name}</strong>
            <span>{line.variantName}</span>
          </div>
          <div class="line-pricing">
            <span>{line.qty} × {line.unitPrice}</span>
            <strong>{line.total}</strong>
          </div>
        </li>
      </template>
    </ul>

    <div class="summary-row"><span>Subtotal</span><span>{subtotal}</span></div>
    <div class="summary-row"><span>Shipping</span><span>{shipping}</span></div>
    <div class="summary-row total-row"><span>Total</span><span>{total}</span></div>
  </template>
</div>

Line Item Variables

VariableDescription
{line.name}Package display name
{line.image}Product image URL
{line.productName}Product name
{line.variantName}Variant name (e.g. "Black / Large")
{line.qty}Quantity
{line.unitPrice}Unit price after discounts
{line.originalUnitPrice}Unit price before discounts
{line.packagePrice}Package total after discounts
{line.originalPackagePrice}Package total before discounts
{line.total}Line total after all discounts
{line.totalDiscount}Total discount on this line
{line.hasDiscount}"show" or "hide"
{line.hasSavings}"show" or "hide"
{line.priceRetail}Retail (compare-at) unit price
{line.isRecurring}"true" or "false"
{line.sku}Product SKU

Step 5: Discount Breakdowns

Show applied offer discounts and coupon codes as separate line items. Add list containers inside your template:

<div data-next-cart-summary>
  <template>
    <div class="row"><span>Subtotal</span><span>{subtotal}</span></div>

    <!-- Offer discounts (e.g. "Buy 2 get 10% off") -->
    <ul data-summary-offer-discounts>
      <template>
        <li class="discount-item">
          <span>{discount.name}</span>
          <span>−{discount.amount}</span>
        </li>
      </template>
    </ul>

    <!-- Applied coupon codes -->
    <ul data-summary-voucher-discounts>
      <template>
        <li class="discount-item coupon">
          <span>{discount.name}</span>
          <span>−{discount.amount}</span>
        </li>
      </template>
    </ul>

    <div class="row"><span>Shipping</span><span>{shipping}</span></div>
    <div class="row total-row"><span>Total</span><span>{total}</span></div>
  </template>
</div>

Discount item variables: {discount.name}, {discount.amount}, {discount.description}.

Full Example

A complete order review summary with line items, discount list, and conditional shipping row:

<div class="order-summary" data-next-cart-summary>
  <template>
    <h3>Order Summary</h3>
    <p class="item-count">{itemCount} item(s)</p>

    <ul class="line-items" data-summary-lines>
      <template>
        <li class="line-item">
          <img src="{line.image}" alt="{line.name}" />
          <div class="line-info">
            <strong>{line.name}</strong>
            <span class="variant">{line.variantName}</span>
          </div>
          <div class="line-price">
            <span>{line.qty} × {line.unitPrice}</span>
            <strong>{line.total}</strong>
          </div>
        </li>
      </template>
    </ul>

    <div class="divider"></div>

    <div class="summary-row"><span>Subtotal</span><span>{subtotal}</span></div>

    <ul class="discounts" data-summary-offer-discounts>
      <template>
        <li><span class="discount-name">{discount.name}</span><span>−{discount.amount}</span></li>
      </template>
    </ul>

    <ul class="discounts" data-summary-voucher-discounts>
      <template>
        <li><span class="coupon-name">{discount.name}</span><span>−{discount.amount}</span></li>
      </template>
    </ul>

    <div class="summary-row shipping-row">
      <span>Shipping</span>
      <span>{shipping}</span>
    </div>

    <div class="divider"></div>

    <div class="summary-row total-row">
      <span>Total</span>
      <strong>{total}</strong>
    </div>

    <div class="summary-row savings-row">
      <span>You save</span>
      <span class="savings-amount">{savings}</span>
    </div>
  </template>
</div>

<style>
  .order-summary {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 10px;
    padding: 1.5rem;
  }
  .line-items { list-style: none; padding: 0; margin: 0 0 1rem }
  .line-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
  }
  .line-item img { width: 48px; height: 48px; object-fit: cover; border-radius: 4px }
  .line-info { flex: 1 }
  .variant { color: #6b7280; font-size: 0.85rem }
  .summary-row {
    display: flex;
    justify-content: space-between;
    padding: 0.35rem 0;
  }
  .total-row { font-size: 1.1rem; font-weight: 700 }
  .divider { border-top: 1px solid #e5e7eb; margin: 0.75rem 0 }
  .discounts { list-style: none; padding: 0; color: #16a34a }
  .discounts li { display: flex; justify-content: space-between }

  /* Hide savings row when there are none */
  .next-no-savings .savings-row { display: none }
  .savings-amount { color: #16a34a }
</style>

On this page