简体   繁体   中英

Accessibility: Best solution to change the icon of an <button roles="button" aria-pressed="true"> when icon is child

I need a toggle button with different icons per state. The icon button looks like this:

<button type="button" role="button" aria-pressed="false">
    <svg class="icon">...</svg>
    <span>Disabled</span>
</button>

What is the better solution from an accessibility point of view if I want to change the icon ( <svg> )?

  1. to have a button with two svg icons, while one is display: none depending on aria-pressed state

  2. to have a button with one svg icon that gets replaced onclick

  3. something else

The simplest solution to this is to not rely on the SVGs at all from an accessibility standpoint.

So for both of them you would use aria-hidden="true" and role="presentation" (as support can be flaky for each in older screen readers).

As you can probably tell I am suggesting having two icons and swapping them out with display:none on one or the other, or better yet why not get fancy and transition between states.

Note it doesn't matter from an accessibility standpoint (as we are hiding them from screen readers) whether you use two images or use one and swap them out with JavaScript, it is just easier to maintain if the icons are within the DOM, rather than having ugly SVG markup in your JavaScript.

You already have some text within the button that says 'disabled' which I am assuming will change to 'enabled' depending on the button state.

At this stage all you need to do is add some visually hidden text (see the CSS below to hide something visually but still allow it to be accessed by the screen reader) explaining the button function.

So if this button was to enable dark theme you would add some visually hidden text to explain the purpose of the button.

Putting that all together you would get something along the lines of:-

<button type="button" role="button" aria-pressed="false">
    <svg class="icon active" aria-hidden="true" role="presentation" focusable="false">...</svg>
    <svg class="icon hidden" aria-hidden="true" role="presentation" focusable="false">...</svg>
    <span class="visually-hidden">Dark Theme </span><span class="state-toggle">Disabled</span>
</button>

Visually Hidden CSS

.visually-hidden { 
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
    white-space: nowrap; /* added line */
}

You will see I added a class "state-toggle" to the <span> you will be toggling from "disabled" to "enabled" just to make it clear, the 'visually-hidden' text should never change. Also note the space after "Dark Theme" to ensure it is read correctly.

I also added 'active' and 'hidden' classes to the two SVGs, obviously you would be better just having one class of 'active' or 'hidden' and default to a state but it was for demonstration purposes.

Also note I added focusable="false" to the SVG as otherwise Internet Explorer may make the SVG focusable due to a bug.

A final consideration is that aria-pressed also has flaky support and you appear to be creating a 'toggle' (albeit with different icons instead of a switch).

What you are doing is perfectly valid and should work but you may consider using a checkbox instead.

Read this in-depth article on different ways to implement toggles written by Hayden Pickering as it provides lots of insights into screen reader behaviour and workarounds for WAI-ARIA support issues / WAI-ARIA fallbacks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM