Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Semantic Html Aria Accessibility Tree

ASecurity

Builds accessible HTML structures using semantic elements (button, nav, main, section, form, fieldset, label) and ARIA 1.2 with clear understanding of accessibility tree, implicit roles, first rule of ARIA, and landmark navigation.

6 stars
0 votes
0 copies
0 views
Added 9/23/2026
developmentgoreactvueawstestingrefactoring

Works with

cli

Security Analysis

A100/100

Scanned 9/23/2026

$npx -y skills add paulpas/agent-skill-router --skill semantic-html-aria-accessibility-tree --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Semantic Html Aria Accessibility Tree?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Semantic Html Aria Accessibility Tree
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-semantic-html-aria-accessibility-tree/badge)](https://www.skillsdirectory.com/skills/paulpas-semantic-html-aria-accessibility-tree)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: semantic-html-aria-accessibility-tree
description: "Builds accessible HTML structures using semantic elements (button, nav, main, section, form, fieldset, label) and ARIA 1.2 with clear understanding of accessibility tree, implicit roles, first rule of ARIA, and landmark navigation."
license: MIT
compatibility: opencode
metadata:
  version: "1.0.0"
  domain: coding
  role: reference
  scope: implementation
  output-format: code
  content-types:
    - reference
    - patterns
    - examples
  triggers: semantic HTML, ARIA 1.2, accessibility tree, implicit roles, HTML5, button, form, landmark
  related-skills: keyboard-navigation-focus-management, wcag-21-aa-fundamentals
  archetypes:
    - educational
    - enforcement
  anti_triggers:
    - component library code
    - styling concerns
    - design patterns
  response_profile:
    verbosity: medium
    directive_strength: high
    abstraction_level: tactical
---

# Semantic HTML & ARIA 1.2: Building the Accessibility Tree

Builds accessible HTML structures using semantic elements and ARIA 1.2, with clear mental model of the accessibility tree, implicit vs explicit roles, and when to use ARIA. Covers HTML5 semantic elements (button, nav, main, section, article, form, fieldset, label), ARIA roles/properties/states, accessibility tree visualization, "first rule of ARIA" (use native HTML), and accessibility tree inspection tools. Load when designing DOM structure, building accessible forms, creating landmark navigation, or understanding how content is exposed to assistive technology.

## TL;DR Checklist

- [ ] Use native HTML elements: `<button>`, `<a>`, `<nav>`, `<main>`, `<article>`, `<form>`, `<fieldset>`, `<label>`
- [ ] Understand implicit roles: `<button>` = role="button", `<nav>` = role="navigation"
- [ ] First rule of ARIA: Never use `role="button"` on `<div>` if `<button>` exists
- [ ] Structure landmarks: `<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>`
- [ ] Associate labels: `<label htmlFor="input-id">` with `<input id="input-id">`
- [ ] Use `aria-label` only for missing text (icon buttons, decorative labels)
- [ ] Test accessibility tree with browser DevTools or axe Inspector
- [ ] Verify screen reader announces correct name, role, state

---

## When to Use

Use this skill when:

- Building new pages or components from HTML (wireframing accessibility)
- Converting divs to semantic elements (refactoring non-semantic markup)
- Adding ARIA attributes to enhance accessibility (when HTML alone insufficient)
- Understanding how content appears to screen readers (accessibility tree)
- Designing page structure with landmarks (nav, main, aside, footer)
- Building accessible forms with proper label associations
- Teaching developers why semantic HTML matters

---

## When NOT to Use

Avoid this skill for:

- React/Vue/Svelte component implementations (use framework-specific skills)
- Styling or CSS (use style-related skills)
- Testing accessibility violations (use automated-a11y-testing-axe-core)
- Keyboard behavior implementation (use keyboard-navigation-focus-management)

---

## HTML5 Semantic Elements Reference

### Document Structure Elements

| Element | Implicit Role | Usage | Screen Reader Announces |
|---------|---|---|---|
| `<header>` | `banner` | Page header (once per page) | "banner" |
| `<nav>` | `navigation` | Navigation section | "navigation" |
| `<main>` | `main` | Main content (once per page) | "main" |
| `<article>` | `article` | Self-contained content | "article" |
| `<section>` | `region` | Generic grouping (use `aria-label` for context) | "region" |
| `<aside>` | `complementary` | Sidebar, related content | "complementary" |
| `<footer>` | `contentinfo` | Page footer (once per page) | "contentinfo" |

### Text Content Elements

| Element | Usage | Semantic Meaning |
|---------|-------|---|
| `<h1>` - `<h6>` | Headings | Document outline hierarchy |
| `<p>` | Paragraphs | Natural text grouping |
| `<blockquote>` | Extended quotes | Attribution context |
| `<ul>`, `<ol>`, `<li>` | Lists | Enumerated/ordered information |
| `<dl>`, `<dt>`, `<dd>` | Definition lists | Terms and definitions |
| `<address>` | Contact information | Author/organization address |

### Interactive Elements

| Element | Implicit Role | Keyboard Support | Usage |
|---------|---|---|---|
| `<button>` | `button` | Enter, Space, Tab | Buttons, form submission |
| `<a href>` | `link` | Tab, Enter | Navigation links |
| `<input>`, `<textarea>`, `<select>` | varies | Tab, input-specific | Form controls |
| `<label>` | `label` | No, associates with input | Form field labels |
| `<fieldset>` | `group` | No, groups inputs | Form grouping |

### Media Elements

| Element | Usage | Accessibility Requirement |
|---------|-------|---|
| `<img>` | Images | alt text (required) |
| `<figure>` | Illustration/diagram | `<figcaption>` for context |
| `<video>` | Video content | captions, transcript, audio description |
| `<audio>` | Audio content | transcript, captions |

---

## Accessibility Tree Mental Model

The **accessibility tree** is a simplified representation of the DOM structure that assistive technologies (screen readers, voice control) use to understand page content.

### How the Accessibility Tree is Built

```
DOM Tree                          Accessibility Tree
─────────────                    ──────────────────

<header>                          "banner" (role)
  <nav>                           ├─ "navigation" (role)
    <ul>                          │  ├─ "Home" (button)
      <li><button>Home</button>   │  ├─ "Products" (link)
      <li><a>Products</a>         │  └─ "Contact" (link)
  </nav>                          │
</header>                         │
<main>                           ├─ "main" (role)
  <h1>Welcome</h1>               │  ├─ "Welcome" (heading level 1)
  <p>...</p>                     │  └─ "..." (paragraph)
  <button aria-label="Search">   │  └─ "Search" (button)
    <svg aria-hidden="true">     │     [decorative, not in tree]
      ...
    </svg>
  </button>
</main>
<footer>                         └─ "contentinfo" (role)
  ...                               └─ "..." (text content)
</footer>
```

**Screen reader reads:**
1. "Banner" (header role)
2. "Navigation" (nav role)
3. List: "Home" (button), "Products" (link), "Contact" (link)
4. "Main" (main role)
5. Heading level 1: "Welcome"
6. Paragraph: "..." (text content)
7. Button: "Search"
8. "Contentinfo" (footer role)

**Key insights:**
- Screen readers announce roles, names, and states from accessibility tree
- Decorative elements (`aria-hidden="true"`) are excluded
- Structure conveyed through semantic elements

### Names, Roles, States

Every item in the accessibility tree has up to three properties:

| Property | Example | How Determined |
|----------|---------|---|
| **Name** | "Search", "Submit", "Home" | Text content, aria-label, title, alt |
| **Role** | "button", "link", "heading" | HTML element or aria-role |
| **State** | "pressed", "expanded", "disabled" | aria-pressed, aria-expanded, disabled |

Screen readers announce: **"{State} {Name} {Role}"**

Examples:
- `<button disabled>Save</button>` → "Disabled Save button"
- `<a href="/home">Home</a>` → "Home, link"
- `<h1>Welcome</h1>` → "Welcome, heading level 1"

---

## The First Rule of ARIA

**Always use native HTML elements first. Only use ARIA when native HTML lacks the required semantics.**

### Why This Rule Exists

1. **Native elements have built-in behavior**: `<button>` responds to Enter/Space without code
2. **ARIA provides only semantics**: It tells screen readers about the element, not keyboard behavior
3. **Maintenance burden**: Custom ARIA components require more code and testing
4. **Better cross-browser support**: Native elements work everywhere

### Consequences of Violating the Rule

```html
<!-- ❌ BAD: ARIA button without keyboard support -->
<div role="button" tabindex="0" @click="handleClick">
  Click me
</div>
<!-- Missing: Enter/Space support, focus management, semantic meaning -->

<!-- ✅ GOOD: Native button -->
<button @click="handleClick">
  Click me
</button>
<!-- Includes: Enter/Space, focus management, inherent semantics -->
```

### When ARIA IS Necessary

Use ARIA only when:

1. **HTML element doesn't exist** for your use case
   - Example: Custom tabs with roving tabindex (HTML has no native tabs)
   
2. **Native element needs role enhancement**
   - Example: `<input type="checkbox">` → `<input type="checkbox" aria-switch>` (not recommended, but valid)

3. **Heading or labeling missing**
   - Example: `<div aria-label="Search Results">` for dynamically generated region

4. **State communication**
   - Example: `<button aria-pressed="true">Toggle</button>` for toggle buttons

---

## Semantic HTML Structure Examples

### Proper Page Structure

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Page Title (appears in browser tab, <title> not visible on page)</title>
</head>
<body>
  <!-- ✅ GOOD: Semantic structure with landmarks -->
  
  <!-- Page header (appears once) -->
  <header role="banner">
    <h1>Site Name</h1>
    <p>Site tagline</p>
  </header>

  <!-- Main navigation -->
  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </nav>

  <!-- Main content (appears once) -->
  <main id="main-content">
    <h1>Page Heading</h1>
    
    <!-- Article content -->
    <article>
      <h2>Article Title</h2>
      <p>Article content...</p>
    </article>

    <!-- Additional articles in section -->
    <section aria-label="Related articles">
      <h2>Related</h2>
      <article>
        <h3>Related Article 1</h3>
      </article>
      <article>
        <h3>Related Article 2</h3>
      </article>
    </section>
  </main>

  <!-- Sidebar (supplementary content) -->
  <aside aria-label="Sidebar">
    <h2>Featured</h2>
    <p>Featured content...</p>
  </aside>

  <!-- Page footer (appears once) -->
  <footer>
    <p>&copy; 2024 Company Name</p>
  </footer>

  <!-- Skip to main content link (keyboard users benefit) -->
  <a href="#main-content" class="skip-link">Skip to main content</a>
</body>
</html>
```

### Accessible Form

```html
<!-- ✅ GOOD: Properly structured form -->
<form id="contact-form">
  <fieldset>
    <legend>Contact Information</legend>

    <!-- Properly labeled text input -->
    <div class="form-group">
      <label for="name">Name</label>
      <input id="name" type="text" name="name" required>
    </div>

    <!-- Email input with helper text -->
    <div class="form-group">
      <label for="email">Email Address</label>
      <input
        id="email"
        type="email"
        name="email"
        required
        aria-describedby="email-help"
      >
      <p id="email-help" class="help-text">
        We'll never share your email
      </p>
    </div>

    <!-- Password with validation -->
    <div class="form-group">
      <label for="password">Password</label>
      <input
        id="password"
        type="password"
        name="password"
        required
        aria-invalid="false"
        aria-describedby="password-requirements"
      >
      <ul id="password-requirements" class="requirements">
        <li>At least 8 characters</li>
        <li>One uppercase letter</li>
        <li>One number</li>
      </ul>
    </div>

    <!-- Checkbox -->
    <div class="form-group">
      <input
        id="terms"
        type="checkbox"
        name="terms"
        required
      >
      <label for="terms">
        I agree to the <a href="/terms">terms of service</a>
      </label>
    </div>

    <!-- Submit button -->
    <button type="submit">Create Account</button>
  </fieldset>
</form>

<!-- ❌ BAD: Inaccessible form -->
<form>
  <!-- Missing label -->
  <input type="text" placeholder="Name">
  
  <!-- Label not associated -->
  <label>Email</label>
  <input type="email">
  
  <!-- No fieldset/legend for grouping -->
  <input type="checkbox">
  I agree to terms
  
  <!-- Missing semantic button -->
  <div role="button" onclick="submitForm()">Submit</div>
</form>
```

### Accessible Navigation

```html
<!-- ✅ GOOD: Semantic navigation -->
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li>
      <a href="/products">Products</a>
      <!-- Submenu -->
      <ul>
        <li><a href="/products/electronics">Electronics</a></li>
        <li><a href="/products/clothing">Clothing</a></li>
      </ul>
    </li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

<!-- ❌ BAD: Non-semantic navigation -->
<div class="navigation">
  <div class="nav-item"><a href="/">Home</a></div>
  <div class="nav-item"><a href="/products">Products</a></div>
  <div class="nav-item"><a href="/about">About</a></div>
</div>
```

---

## ARIA Roles, Properties, and States

### ARIA Roles (Define Purpose)

```html
<!-- Roles define what an element does -->

<!-- Navigation role (use <nav> instead) -->
<div role="navigation">Links here</div>

<!-- Tablist with roving tabindex -->
<div role="tablist">
  <button role="tab" aria-selected="true" tabindex="0">Tab 1</button>
  <button role="tab" aria-selected="false" tabindex="-1">Tab 2</button>
</div>

<!-- Alert role (for status messages) -->
<div role="alert">Error: Password too short</div>

<!-- Status role (for updates) -->
<div role="status" aria-live="polite">Loading...</div>
```

### ARIA Properties (Describe Characteristics)

```html
<!-- aria-label: Provide name when text unavailable -->
<button aria-label="Close dialog">×</button>

<!-- aria-labelledby: Connect to existing text -->
<h2 id="dialog-title">Delete Item</h2>
<div role="dialog" aria-labelledby="dialog-title">
  ...
</div>

<!-- aria-describedby: Provide description -->
<input
  type="password"
  aria-describedby="pwd-requirements"
>
<p id="pwd-requirements">8+ characters, 1 number, 1 uppercase</p>

<!-- aria-required: Indicate required field -->
<input type="email" aria-required="true">

<!-- aria-invalid: Indicate invalid state -->
<input type="email" aria-invalid="true">
```

### ARIA States (Describe Current Condition)

```html
<!-- aria-expanded: Indicate collapsed/expanded state -->
<button aria-expanded="false" aria-controls="menu">
  Menu
</button>
<ul id="menu" hidden>...</ul>

<!-- aria-selected: Indicate selected tab/option -->
<button role="tab" aria-selected="true">Tab 1</button>
<button role="tab" aria-selected="false">Tab 2</button>

<!-- aria-pressed: Indicate toggled button state -->
<button aria-pressed="false" @click="toggle()">
  Toggle
</button>

<!-- aria-disabled: Prevent interaction (supplementary to disabled) -->
<button aria-disabled="true">Disabled</button>
```

---

## Accessibility Tree Inspection

### Browser DevTools (Chrome/Firefox)

1. Open DevTools → Accessibility tab
2. Expand accessibility tree
3. Click element in tree to highlight in DOM
4. Inspect: name, role, state, parent relationships

### WAVE Browser Extension

1. Install WAVE for Chrome/Firefox
2. Open page, toggle wave overlay
3. Shows structure with landmarks highlighted
4. Color-codes accessibility issues

### Testing Approach

Verify accessibility tree matches:
- Document landmarks (header, nav, main, aside, footer)
- Heading hierarchy (H1 → H2 → H3, no skips)
- Form labels (properly associated inputs)
- Links and buttons (proper roles)
- Dynamic content announcements

---

## Constraints

### MUST DO

- Use semantic HTML elements for all content (button, nav, main, article, aside, footer)
- Associate labels with form inputs using `<label htmlFor="id">`
- Structure page with landmarks: header, nav, main, aside, footer
- Use heading hierarchy without skipping levels (H1 → H2 → H3)
- Provide descriptive text for images using `<img alt="description">`
- Use `aria-label` only when visible text unavailable (icon buttons, regions)
- Test accessibility tree with browser DevTools or WAVE
- Never use `role="button"` on `<div>` when `<button>` exists

### MUST NOT DO

- Use `<div>` and `<span>` for interactive elements (use button, a, input)
- Remove implicit roles with conflicting explicit roles (confusion)
- Use decorative elements in accessibility tree (mark with `aria-hidden="true"`)
- Skip heading levels (H1 → H3, skipping H2)
- Leave images without alt text or with placeholder alt text
- Use `aria-label` as substitute for proper HTML structure
- Assume ARIA fixes structural problems (it doesn't)
- Place form labels outside `<label>` elements without `aria-label`

---

## Accessibility Tree Checklist

For any page or component, verify:

- [ ] All interactive elements are native (button, a, input, select, textarea)
- [ ] All form inputs have `<label>` or `aria-label`
- [ ] Page has H1 and proper heading hierarchy (no skips)
- [ ] Landmarks present: header, nav, main, footer
- [ ] Images have descriptive alt text
- [ ] Color alone doesn't convey information
- [ ] Focus order logical (Tab through page in logical sequence)
- [ ] Accessibility tree includes all essential content
- [ ] Decorative elements marked `aria-hidden="true"`
- [ ] Links and buttons have descriptive text (not "Click here")

---

## Core Workflow: Converting Non-Semantic to Semantic

1. **Audit Current Structure** — Identify divs used for buttons, navigation, sections
2. **Map to Semantic Elements** — Replace with proper HTML elements
3. **Add Landmarks** — Wrap content in header, nav, main, aside, footer
4. **Associate Labels** — Add proper label elements and aria-label
5. **Add Heading Structure** — Create H1-H6 hierarchy matching content
6. **Test Accessibility Tree** — Verify structure with DevTools or WAVE
7. **Validate with Screen Reader** — Test with NVDA/JAWS/VoiceOver

Attribution

paulpaspaulpas
View sourceSee grades on GitHubMore from paulpas →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

286712 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Writing Plans

Use when you have a spec or requirements for a multi-step task, before touching code

2927051 votes
View all in development →