Search code examples
htmlaccessibilitywai-aria

Composite label for checkbox


I have this page:

<!DOCTYPE html>
<html>
  <head>
    <title>Page Title</title>
  </head>
  <body>
    <div>
      <label class="Label">Options</label>
    </div>
    <div>
      <input type="checkbox" id="checkbox1" aria-checked="false">
      <label for="checkbox1">content 1</label>
    </div>
  </body>
</html>

which looks like this: enter image description here

When I use Microsoft narrator (to check my website accessibility), I want the user to know that "content 1" is associated with "Options" I tried to use aria-label:

<input type="checkbox" id="checkbox1" aria-checked="false" aria-label="options">
<label for="checkbox1">content 1</label>

But then the narrator reads only "options" and skip the "content 1". What am I missing here? I would like the narrator to read "options" and "content 1" when marking the checkbox.


Solution

  • I use VoiceOver but hopefully this would work with your screen reader of choice.


    If I understand correctly you want screen readers to announce both "Options" and "content 1" or to somehow let screen readers know that both are related.

    Option 1: Use native semantic

    Probably your best bet is to rely on semantic HTML:

    <html>
      <body>
        <h1>Form</h1>
        <fieldset>
          <legend>Options</legend>
          <input type="checkbox" name="opts" id="cb1">
          <label for="cb1">Content 1</label>
        </fieldset>
      </body>
    </html>
    

    Note: with a bit of CSS you can remove the default browser styles for fieldsets.

    Here's how Voice Over announces the checkbox:

    enter image description here

    Option 2: compose label from other elements on the page

    Another option is to use aria-labelledby which takes a list of html ids and screen readers will form a sentence with the corresponding html elements:

    <html>
      <body>
        <h1>Form</h1>
        <div id="group">Options</div>
        <div>
          <input type="checkbox" name="opts" id="cb1" aria-labelledby="group label1">
          <label for="cb1" id="label1">Content 1</label>
        </div>
      </body>
    </html>
    

    And here's how Voice Over announces it:

    enter image description here


    Addendum: don't use aria-checked with native checkboxes

    If you rely on native checkboxes and don't intend to programmatically control them then you have no reason to use aria-checked. Let the browser do the work for you; screen reader users will thank you ;)

    Here's an example of an author wanting to preselect a checkbox with checked="checked" but left a aria-checked="false" attribute.

    <html>
      <body>
        <input type="checkbox" id="cb1" checked="checked" aria-checked="false">
        <label for="cb1">content 1</label>
      </body>
    </html>
    

    Here's how Voice Over announces the checkbox:

    enter image description here

    As you can see the screen reader is confused and think the checkbox is not checked. If the screen reader user wanted to check it, they would actually uncheck the box!