Here’s a quick quiz! What’s the price of this item?

Product page showing two jacket images, a red “Sale” label, product title “Awesome product sale”, discounted price £135.99 reduced from £159.99, descriptive marketing text, and a prominent “Add to basket” button.

You might say: Easy - It’s £135.99 . And you’d be right. But that’s because you can see it.

But unless this sale price is explicitly explained and exposed in the page markup, then for someone using a screen reader, both prices are just read out in sequence: “£135.99 £159.99”.

There’s no indication of which is the real price. It’s exactly the same as showing two unstyled prices for everyone - which one is correct?

Now - a user may infer that the lower price is the sale price. But they have to infer it, and that single moment causes doubt - and you don’t want doubt.

You want clarity.

If you saw two prices and were not certain which one applied, would you confidently click Add to Basket?

If you saw two unstyled prices and you weren’t 100% sure which was the real price, would you still click Add to Basket? I’m not sure I would bother. You may be able to argue that if this was just the single point of failure on your product pages - you may be forgiven for some slight ambiguity. But are you sure that’s the case?

And this is the whole point for testing your product pages. Remember - not everyone shops like you do.

What does your code look like?

Here’s what that code in that screenshot often looks like:

<div>
  <span class="product-price__current">£135.99</span>
  <span class="product-price__previous">£159.99</span>
</div>

From a screen reader’s perspective, both prices are simply read in sequence. There is nothing in the markup that explains the relationship between them.

This is so common “in the wild” - and it’s so easy to fix. Here’s a tiny change that makes the pricing less broke, and more usable for everyone.

<div>
  <span class="visually-hidden">Sale price:</span>
  <span class="product-price__current">£135.99</span>
  <span class="visually-hidden">Previous price:</span>
  <span class="product-price__previous">£159.99</span>
</div>

This is a small change in markup, but it removes the ambiguity completely. A more resilient implementation makes pricing relationships explicit.

A screen reader will now announce: “Sale price: £135.99, Previous price: £159.99”. The relationship between the values is explicit . Ambiguity gone 🎉.

There are many ways you could fix this broken pattern, and the example above is just one way - but the point is it turns a confusing moment into a confident one. And it builds trust with your customer.

Here’s another way. If you don’t want any hidden text - then simply adding some text making it clear that this is the sale price. In this screenshot the price clearly tells you that the product is 20% off.

Product page showing a jacket on sale priced at £200 with “Save 20%” displayed next to it, previous price £250 struck through below, star rating with 875 reviews, size dropdown, and “Add to basket” button.

The principle is consistent: Meaning must be encoded in the markup, not inferred from styling.

This makes sure every customer knows the price they’ll pay - not just the ones who can visually see it.

Why this matters beyond accessibility

As commerce expands across voice interfaces, AI shopping agents, and embedded experiences, structured clarity becomes increasingly important.

Machines do not interpret colour, font size, or strikethrough as meaning. Instead, they rely on explicit labels, consistent structure, and deterministic state representation. Sounds familiar? It’s almost as if building highly structured and easy to use product pages benefits everyone!

Accessible pricing is therefore not only more inclusive. It is machine-readable. And machine-readable systems scale. Ambiguity does not.

Auditing your own pricing implementation

You can easily evaluate pricing clarity across your own product pages with a simple three-part review:

  1. Screen reader review - Use NVDA, VoiceOver, or JAWS.

    Navigate to the price and listen carefully. Is the current price clearly identified? Is the previous price clearly described? Is there any ambiguity about which value applies?

  2. Markup inspection - Inspect the DOM.

    Are prices distinguished structurally, or only stylistically? Does the order of elements reflect logical meaning? Are obsolete values still exposed?

  3. Interaction testing - Change a variant.

    Is the new price announced? Is the old value removed or correctly hidden? Is the final payable amount explicit?

If any of these steps require interpretation, your pricing structure can be improved.

The core requirement is that your product page must clearly answer: What exactly will I be charged right now?

Not visually or stylistically. But structurally.

If the answer depends on inference, your page introduces unnecessary cognitive load.

If the answer is explicit in the markup, your page supports confident decision-making.

Clear pricing does not make a site impressive.

It makes it reliable.

And reliability is what protects conversion.