What this example teaches

  • How empty icon buttons get accessible names.
  • When visible text is better than aria-label.
  • How toggle and submit buttons communicate state and purpose.

Empty icon button

Bad

<button><svg aria-hidden="true"><!-- icon --></svg></button>

The button has no accessible name.

Better

<button aria-label="Search"><svg aria-hidden="true"><!-- icon --></svg></button>

The icon-only button now has a clear accessible name.

Visible button text

Bad

<button aria-label="Send message">Submit</button>

The visible text and accessible name do not match, which can confuse speech input users.

Better

<button type="submit">Send message</button>

Visible text gives the button a clear name for everyone.

Toggle button state

Bad

<button>Show filters</button>

Users may not know whether the filter panel is currently open.

Better

<button type="button" aria-expanded="false" aria-controls="filters">Show filters</button>
<section id="filters" hidden>...</section>

The button exposes its relationship and expanded state.

Best after opening

<button type="button" aria-expanded="true" aria-controls="filters">Hide filters</button>
<section id="filters">...</section>

The label and state update together.

Submit button clarity

Bad

<button type="submit">Go</button>

Go is vague when the form action matters.

Better

<button type="submit">Request accessibility review</button>

The button describes the form submission outcome.

What still needs human review

  • Whether button labels match the actual action and current state.
  • Whether keyboard focus, disabled states, menus, modals, and toggles behave correctly.
  • Whether custom button-like elements should be native button elements instead.

Related tools

Related issue library pages

Related guides and resources

Recommended next steps