Search code examples
accessibilityscreen-readersjaws-screen-readernvda

accessibility p tag different text for screen reader


For a p tag, I need the text that a screen reader reads to be different than the text contained in the p tag. I need humans to see "Jordan" and the screen reader to read "Michael Jordan." These are in a responsive grid with swiper.js. Adding title didn't work. How do I get this to work? (I can use a different HTML tag and attribute to get the same effect.)

<p role="title" title="Michael Jordan">Jordan</p>

Solution

  • The golden rule of accessibility is to offer as similar an experience to screen reader users as possible to non screen reader users, as such the following techniques should be used sparingly.

    With that being said sometimes context etc. can be important and you need to provide extra information to screen readers.

    There are numerous ways to do this:

    1. aria-label

    If you give an element an aria-label its contents are overridden. However this doesn't have perfect support, especially on elements such as paragraphs and divs without roles etc.

    <p aria-label="Michael Jordan">Jordan</p>

    Update on aria-label usage for clarity

    I was not clear above as pointed out in the comments.

    Hopefully this is more clear, my apologies:

    Screen readers will ignore aria-label on paragraphs, divs, etc. unless they have a role that overrides their semantic meaning.

    For example:

    <p aria-label="Michael Jordan" role="heading">Jordan</p> will work whereas the example I gave above will not and was purely to illustrate aria-label usage.

    2. Visually Hidden Text

    A far more robust way of providing extra information to screen reader users is to use visually hidden text.

    .visually-hidden { 
        border: 0;
        padding: 0;
        margin: 0;
        position: absolute !important;
        height: 1px; 
        width: 1px;
        overflow: hidden;
        clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
        clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
        clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
        white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
    }
    <p><span class="visually-hidden">Michael </span>Jordan</p>

    Additional important information

    As far as I am aware there is no such thing as role="title" - I assume you meant something like role="heading" - at which point just use a <h1> to <h6>.

    I removed the title attribute from both examples, it is essentially useless nowadays with touch devices not being able to access it, keyboard users never seeing it and it being ignored by a lot of screen readers, generally the advice would be not to use it.

    Final thoughts

    Also be aware, for screen reader users who navigate via mouse (i.e. people who use screen readers to assist in comprehension) neither of the above techniques are likely to change what they hear when they mouse over.

    As such having the full words would be preferable if you can redesign your interface to accommodate the extra text. Doing this removes the need for any additional markup too so would be the preference.

    <p>Michael Jordan</p>.