2
votes

I have a two-sided mobile menu drawer that relies on a hidden checkbox for switching/toggling between its two sides.

There are two LABEL elements, one on each side of the menu drawer. Each LABEL, via its FOR attribute, references the ID of the hidden INPUT checkbox. Clicking a displayed LABEL thus checks the INPUT checkbox and causes the menu to switch sides (via CSS). A distillation of the HTML is:

<ul class=main-menu>
    <li>
        <input id=toggle-drawer type=checkbox title="hidden checkbox">
        <label for=toggle-drawer>See Sub Menu</label>
        <ul class=sub-menu>
            <li>
                <label for=toggle-drawer>See Main Menu</label>
            </li>
            <li>Sub-menu item 1</li>
            <li>Sub-menu item 2</li>
            <li>Sub-menu item 3</li>
        </ul>
    </li>
    <li>Main Menu item 1</li>
    <li>Main Menu item 2</li>
    <li>Main Menu item 3</li>
</ul>

It is, in fact, perfectly valid HTML to have multiple labels that reference the same input item.

See https://www.w3.org/TR/html401/interact/forms.html#h-17.9.1 :

"More than one LABEL may be associated with the same control by creating multiple references via the for attribute."

However, the WebAIM WAVE (Web Accessibility Evaluation Tool) browser extension flags the two labels as an error, stating,

"A form control should have at most one associated label element. If more than one label element is associated to the control, assistive technology may not read the appropriate label."

As a remedy, it goes on to state:

"If multiple form labels are necessary, use aria-labelledby."

aria-labelledby seems not to apply to my case, as it would be put on an INPUT item that is referenced by a DIV, etc.

Is there an ARIA or similar mark-up method I can use to satisfy this accessibility audit? I do not wish to alter my HTML structure.

1

1 Answers

6
votes

Although it is perfectly valid HTML, having two labels will cause issues with NVDA and possibly other screen readers where it will only read one label.

This is why WAVE suggests you use aria-labelledby as that is designed to take multiple elements and can combine them (in the order you list them).

It is perfectly valid to use this on an input, also note that aria-labelledby will override any associated <label> elements using for="id"

One thing you could do is use the less often used aria-describedby to associate the second label and ensure that the reading order is correct.

In the example below it would read 'See Main Menu, See Sub Menu' as it will read the <label for="toggle-drawer"> first and then use the aria-describedby="toggle-drawer-label" to add additional information.

The only down side is that it may read the input information in between the <label> and the describedby label.

<ul class=main-menu>
    <li>
        <input id="toggle-drawer" aria-describedby="toggle-drawer-label" type=checkbox title="hidden checkbox">
        <label id="toggle-drawer-label">See Sub Menu</label>
        <ul class=sub-menu>
            <li>
                <label for="toggle-drawer">See Main Menu</label>
            </li>
            <li>Sub-menu item 1</li>
            <li>Sub-menu item 2</li>
            <li>Sub-menu item 3</li>
        </ul>
    </li>
    <li>Main Menu item 1</li>
    <li>Main Menu item 2</li>
    <li>Main Menu item 3</li>
</ul>

The recommended way

I would recommend simply using aria-labelledby="label1 label2" as that is the accepted method and will result in the most consistent results, obviously it means you need to add id attributes to both labels so that is the trade off.

Note that using aria-labelledby="label1 label2" and associating the fields with for="toggle-drawer" on both labels has the added benefit of correctly linking the labels so that you can click on either label and it will focus the <input>.