Search code examples
htmlaccessibilitywai-ariascreen-readers

Accessibility for label value scenarios


I have a question on the right way to make a label and its value accessible to the user. For example I have a section which shows the following details of the user

  1. First Name John
  2. Last Name Smith

In the HTML I can have two columns to represent this. Something like below

<div class='row'>
  <div class="col">First Name</div>
  <div class="col">John</div>
</div>
<div class='row'>
  <div class="col">Last Name</div>
  <div class="col">Smith</div>
</div>

But when I do this, the screen reads them one by one. Rather than telling *First Name John * (read it together) it reads as

First Name

John

(reading it only after I use the down arrow on keyboard) Which I don't think is right. (I have use the arrow key to get the name John Smith read out. It does not read First Name and John Smith together)

<div class='row'>
  <div class="col" id='first-name'>First Name</div>
  <div class="col" aria-labelledby='first-name'>John</div>
</div>
<div class='row'>
  <div class="col" id='last-name'>Last Name</div>
  <div class="col" aria-labelledby='last-name'>Smith</div>
</div>

still the way it reads is the same.

Could you please suggest what's the right way to implement this making it accessible for all?


Solution

  • Any text contained in separate <div>s will be treated as new paragraphs and so will introduce a pause.

    Additionally you cannot put an aria-label on a <div> and get consistent results (you could give it a role to make it work, however there is no role that is appropriate for this that I can think of).

    The easiest way to achieve what you are after is to hide the original 2 columns from a screen reader using aria-hidden="true" and then add a visually hidden piece of text with the complete text inside <p class="visually-hidden">First Name, John</p>.

    I have put an example below that should behave as expected.

    .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 */
    }
    <div class='row'>
      <div class="col" aria-hidden="true">First Name</div>
      <div class="col" aria-hidden="true">John</div>
      <p class="visually-hidden">First Name, John</p>
    </div>
    <div class='row'>
      <div class="col" aria-hidden="true">Last Name</div>
      <div class="col" aria-hidden="true">Smith</div>
      <p class="visually-hidden">Last Name, Smith</p>
    </div>

    Warning - are you sure you want to interfere with a screen reader?

    99% of the time you should not manipulate how a screen reader reads things with labels, hidden text etc.

    I actually think the original behaviour is correct (but that is based on information out of context).

    You have separate columns and so reading each column in order makes sense.

    However without seeing the application, context etc. It is not possible to make anything other than guesses so I have given this example the benefit of the doubt.

    I would think carefully before implementing my solution as reading each div separately is expected behaviour, they are read in the correct order so I do not think there would be a problem with this in 99% of scenarios.

    You should also consider whether the divs should contain paragraphs to be semantically correct (i would say yes, even if that does require some styling to remove margin etc. but it is a minor point).

    Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable. Use of more appropriate elements instead of the div element leads to better accessibility for readers and easier maintainability for authors.

    taken from https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element