← Back to Frontend and design systems

Skill · Version 1.0.0

Semantic HTML and accessible names

Makes interface structure, controls and states understandable to assistive technology using meaningful native HTML.

semantic-html-accessible-names

Team members using this skill

See how it helps

When is it useful?

Use when a screen reader announces unlabeled controls or confusing structure.

What does it help you do?

  • Chooses native buttons, links, form labels and landmarks.
  • Keeps accessible names consistent with visible control text.
  • Reports actual disabled, expanded and selected states honestly.

Try asking this

Audit icon actions and form fields so each has a meaningful name and correctly announced state. Inspect an icon-only delete button and an expandable filter. Their accessible names should describe the action, and expanded state must match the actual visible panel.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Semantic HTML & Accessible Names

Assistive technologies rely on the browser's accessibility tree — computed from HTML elements, attributes and ARIA — to convey role, accessible name, state/value and document structure (WCAG 4.1.2, 1.3.1, 2.4.6, 2.5.3). Always start from native HTML elements before reaching for ARIA.

1. Native HTML First vs. Custom Elements

  • First Rule of ARIA: if a native HTML element or attribute provides the semantics and keyboard behavior you need, use it directly (<button type="button">, <a href="...">, <input>, <select>, <textarea>, <dialog>, <details>/<summary>, <table>, <fieldset>/<legend>).
  • Button vs. Link:
    • Use <a href="..."> for navigation that changes the URL or moves to a document/section. An <a> without an href is not keyboard-focusable.
    • Use <button type="button"> for in-page actions (opening a dialog, toggling state, submitting/deleting, sorting a table column, triggering a menu).
  • Never attach click handlers to bare <div>, <span> or <svg> without a native interactive element or full role, tabindex="0", Enter/Space keyboard handling and state synchronization.

2. Landmarks, Document Regions & Heading Hierarchy

Screen reader users navigate pages by jumping across landmarks and headings:

  • Page landmarks: structure views with <header> (banner), <nav> (navigation), <main> (main, one visible per view), <aside> (complementary) and <footer> (contentinfo).
  • Disambiguate multiple landmarks of the same type: give multiple <nav> or <section>/<aside> landmarks distinct accessible names via aria-label or aria-labelledby (without repeating "navigation" inside aria-label).
  • Logical heading outline (<h1>–<h6>): provide a clear <h1> for the current view and nest <h2>–<h6> by logical containment rather than visual font size.

3. Accessible Name Computation & Label in Name

Follow the W3C Accessible Name and Description Computation priority order:

  1. aria-labelledby (overrides all other name sources — references space-separated IDs, even if hidden).
  2. aria-label (overrides visible text content inside the element).
  3. Native host-language association (<label for="...">, <legend> for <fieldset>, <caption> for <table>, alt for <img>, subtree text for <button>/<a>).
  4. Fallback attributes (title or placeholder — fragile, never use as primary label).
Critical Naming Rules
  • WCAG 2.5.3 Label in Name: when a control has a visible text label, its accessible name must contain the visible text string (ideally starting with it) so voice-control users saying "Click Save changes" can activate it. Never put aria-label="Submit form" on a button whose visible text says Save changes.
  • Icon-only controls: give every icon-only button or link a concise aria-label (or visually hidden text), with aria-hidden="true" focusable="false" on the inner <svg>.
  • Repeating row/card actions: in lists or tables with repeated buttons (Edit, Delete), disambiguate via aria-label="Edit invoice #1042" or aria-labelledby combining the action and row identifier.

4. Honest States & Properties

  • Synchronize states in real time: aria-expanded="true|false" on disclosures/menus, aria-pressed="true|false" on toggles, aria-selected="true|false" on tabs/options, aria-current="page|step" on active nav items, and disabled / aria-disabled="true" when unavailable.
  • Never leave dangling IDs in aria-labelledby, aria-describedby, aria-controls or aria-owns when targets unmount.

Included files 1

  • SKILL.md