htmlaccessibilityscreen-readers

Screen reader is not reading the price ("$47.49") properly


I am trying to make the screen reader (NVDA) to read my currency value (US dollar) $47.49 as "47 Dollars 49 Cents", but the screen reader is reading my currency value as "Dollar 4749".

<div class="perVendorCarDetails">
  <span class="carCurrencySymbol">$</span> 
  <span class="carPriceDollar">38</span>           
  <span class="carPriceDot">.</span> 
  <span class="carPriceCents">57</span>
</div>

Solution

  • Your example is spoken by NVDA/Firefox as "dollar thirty-eight dot fifty seven." This is not good.

    If you just coded it as <p>$38.57</p> it would be read as "dollar thirty-eight point five seven." As unpleasant as that seems/is, it is what NVDA users expect.

    If I go to Amazon, for example, I get "dollar one point two nine" for $1.29. Target, which went through a pretty widely-publicized accessibility lawsuit, hired an accessibility consulting firm, built an accessibility team, and performed extensive testing with screen readers, announces $39.99 as "dollar thirty-nine point nine nine."

    So the most important thing you may want to do is not confuse NVDA users when they want to spend money. Presenting dollar values in a different way than they expect can do that.

    However, if you are adamant that this must happen, you can use aria-hidden to hide the value you do not like from NVDA, and then you can write the phrase that you want into the page after it, hiding it from all other users via an off-screen CSS technique intended to do just this.

    Your new HTML:

    <p aria-hidden="true">
      $38.57
    </p>
    <span>38 dollars and 57 cents</span>
    

    Obviously you will need to break the dollar amount into two variables and write each twice.

    The aria-hidden="true" hides the <p> text from screen readers, so a screen reader will only read what is in the <span>.

    Now the CSS to hide the contents of the <span> from your users:

    p[aria-hidden=true] + span {
      position: absolute;
      clip: rect(1px 1px 1px 1px);
      clip: rect(1px, 1px, 1px, 1px);
      padding: 0;
      border: 0;
      height: 1px;
      width: 1px;
      overflow: hidden;
    }
    

    You will clearly need to change the selector based on your elements, IDs, classes, etc.