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
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?
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>
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