Fixes · Sale prices and variants

Compare-at price disappears when you change size

The fix

The price is drawn twice: by Liquid when the page loads, and again by the theme’s script each time a size or colour is picked. If the script’s sale check is wrong, the crossed-out price shows on load and disappears on the first change.

Make the script compare the same two numbers Liquid does: the variant’s compare-at price and its price, both in the currency’s smallest unit (pence on a UK store). Better still, let Shopify draw the new price block for you, as its Dawn theme does.

01Why the price changes after a click

On this Shopify Community thread (Oct 2021), a merchant’s price vanished whenever a shopper picked another variant, but showed correctly after a reload or on a variant’s own link. The poster came back the next day to say “I figured out the problem” without saying what it was, and people were still asking how in 2022 and 2024. Right on load and wrong after a change is the clue.

  1. 01

    Two renderers, two checks

    Liquid decides on load, with a check like {% if current_variant.compare_at_price > current_variant.price %}. The theme’s script redraws the price block on every change with its own version of that check. When the two disagree, the page is right until the shopper touches it.

  2. 02

    The script compares the wrong number

    Liquid gives variant.price and variant.compare_at_price “in the currency’s subunit” (Shopify, the variant object): £50.00 is 5000. On the store we fixed, the script compared the compare-at price in pence with the option’s value, which was the variant’s ID, a 14-digit number. The compare-at price was never the bigger of the two, so every change drew the plain price.

  3. 03

    Sometimes it isn’t the theme

    If the compare-at price is missing on load as well, look at apps first. On this thread (Sep 2024) it was missing for every variant, and the reply found “A 3rd party app you are using hides the default price of your theme.”

02Make the script check what Liquid checks

For store owners: check a sale product

  1. Find a product on sale in more than one size

    In Products, open the product and check that each size has a Compare-at price higher than its Price.

  2. Open it on the store and pick another size

    The crossed-out price should stay. If it shows on load and vanishes on the first change, the theme’s script is redrawing it wrongly.

  3. Reload on the new size

    If the crossed-out price comes back after a reload, that confirms it: the page’s first draw is right and the redraw is wrong. Send the product link to your developer.

For developers: one check, in pence

Put each variant’s price in pence on its option, beside the compare-at price, and compare those two, as Liquid does. This is the shape of what we shipped, generalised:

Each option carries both prices in pence (Liquid)liquid
{%- for variant in product.variants -%}
  <option
    value="{{ variant.id }}"
    data-price="{{ variant.price | money }}"
    data-compare-price="{{ variant.compare_at_price | money }}"
    data-price-cents="{{ variant.price }}"
    data-compare-cents="{{ variant.compare_at_price | default: 0 }}"
    {% if variant == product.selected_or_first_available_variant %}selected{% endif %}
  >{{ variant.title | escape }}</option>
{%- endfor -%}
The redraw makes the same check as Liquidjs
function renderPrice(option, priceEl) {
  const price = parseInt(option.dataset.priceCents, 10);
  const compare = parseInt(option.dataset.compareCents, 10);

  // compare_at_price > price, both in pence: the check Liquid makes on load.
  if (compare > price) {
    priceEl.innerHTML =
      '<span class="price price--sale">' + option.dataset.price + '</span>' +
      '<s class="price price--compare">' + option.dataset.comparePrice + '</s>';
  } else {
    priceEl.innerHTML = '<span class="price">' + option.dataset.price + '</span>';
  }
}
  • Never read a price from option.value. On a product form it holds the variant ID, because that is what the cart needs.
  • Compare numbers, never formatted money such as “£50.00”.
  • Liquid outputs prices in the shopper’s local currency (Shopify, the variant object), so the attributes follow the market the page was drawn for.
  • Better: don’t redraw the price in your script at all. Dawn fetches the section again for the chosen variant (section_id and option_values in the request) and swaps in the price block Shopify drew, so there is one renderer (Dawn, product-info.js; Shopify, Section Rendering API).

03Change size, then change back

  1. Change size on a sale product

    The crossed-out price should stay on every size that has one.

  2. Change to a size that isn’t on sale, and back

    On a product where only some sizes are reduced, the crossed-out price should go and come back.

  3. Try every other place that redraws a price

    A second product template, a quick view, a sticky add-to-cart bar. Each one with its own script needs the same check.

From our work

04A sportswear retailer’s sale items

A sportswear retailer we look after, with a UK and a US store, told us that on sale items the crossed-out price disappeared as soon as you changed size. The first thought was that two colours had been set up differently, but both screenshots the team sent were of the same colour.

The cause (4 Jun 2026). Both stores ran the same theme code. On load the price block was right, because Liquid compared the compare-at price with the price. The script that redrew it on every size change compared the compare-at price in pence with the option’s value, the variant’s ID, so the sale branch never ran. The same line sat in two templates, the main product page and a second product template, on both stores.

The fix (4 Jun 2026). Each option now carries its price in pence, and the script compares against it: the check Liquid makes. Both templates on both stores, the same day.

  • In our log“Sale items keep their crossed-out price when a shopper changes size”

The bigger picture

05Two renderers that disagree

A page that is right on load and wrong after a click has two renderers that disagree. The price is the one shoppers notice. Stock messages, badges and sold-out buttons are often drawn the same way, and can drift the same way.

Finding where a theme draws the same thing twice, and making it draw once, is part of our development work.

06Sources

Every step and claim above comes from one of these, or from the fix on the store it describes.

  1. Shopify developers: Liquid objects, variant
  2. Shopify developers: Section Rendering API
  3. Shopify Dawn theme: assets/product-info.js
  4. Shopify Community: On PDP, product price disappears when I select a variant (Oct 2021)
  5. Shopify Community: Compare at price not showing for variants, Dawn theme (Sep 2024)

Sources checked on .

Contact

Prices changing after a click?

Send us a sale product’s link and tell us what you expected to see.