Receber por email
← Voltar para o catálogo

accessibility-patterns

Provides web accessibility best practices for semantic HTML, ARIA, keyboard navigation, color contrast, and screen reader patterns. Use when building UI components, reviewing accessibility, or when user mentions 'a11y', 'accessibility', 'ARIA', 'screen reader', 'keyboard navigation', 'WCAG'.

65estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: NOASSERTION

Como adicionar

/plugin marketplace add Tibsfox/gsd-skill-creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/accessibility-patterns-tibsfox/svg)](https://www.skillteca.com.br/skills/accessibility-patterns-tibsfox)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Accessibility Patterns

Reference guide for building inclusive, accessible web interfaces that comply with WCAG 2.1 AA standards.

Core Principles (POUR)

| Principle | Meaning | Key Question | |-----------|---------|-------------| | Perceivable | Content is available to all senses | Can users see, hear, or read it? | | Operable | Interface works with all input methods | Can users navigate with keyboard only? | | Understandable | Content and UI are predictable | Can users understand and recover from errors? | | Robust | Works across assistive technologies | Does it work with screen readers and future tools? |

Semantic HTML Reference

Use the right element for the job. Semantic HTML provides accessibility for free.

Document Structure

<header>     <!-- Site/section header, landmarks for screen readers -->
<nav>        <!-- Navigation links, announced as "navigation" -->
<main>       <!-- Primary content, skip-to target -->
<article>    <!-- Self-contained content (blog post, card) -->
<section>    <!-- Thematic grouping with heading -->
<aside>      <!-- Tangentially related (sidebar, callout) -->
<footer>     <!-- Site/section footer -->

Interactive Elements

| Need | Use | NOT | |------|-----|-----| | Clickable action | <button> | <div onclick> or <span onclick> | | Navigation link | <a href="..."> | <div onclick="navigate()"> | | Text input | <input type="text"> | <div contenteditable> | | Selection | <select> + <option> | Custom dropdown without ARIA | | Toggle | <input type="checkbox"> | <div class="toggle"> | | Form group | <fieldset> + <legend> | <div class="form-group"> |

Heading Hierarchy

<!-- CORRECT: Logical hierarchy, no skipped levels -->
<h1>Page Title</h1>
  <h2>Section</h2>
    <h3>Subsection</h3>
    <h3>Subsection</h3>
  <h2>Another Section</h2>

<!-- WRONG: Skipped levels, multiple h1, heading for styling -->
<h1>Title</h1>
<h1>Another Title</h1>  <!-- Only one h1 per page -->
  <h4>Jumped from h1 to h4</h4>  <!-- Skipped h2, h3 -->

ARIA Roles, States, and Properties

ARIA supplements HTML semantics. The first rule of ARIA: do not use ARIA if native HTML provides the semantics.

Landmark Roles

Most of these are already implied by semantic HTML.

| Role | HTML Equivalent | When to Use ARIA | |------|----------------|-----------------| | banner | <header> (top-level) | Nested headers needing landmark | | navigation | <nav> | Rarely needed | | main | <main> | Rarely needed | | complementary | <aside> | Rarely needed | | contentinfo | <footer> (top-level) | Nested footers needing landmark | | search | <search> | Browsers without <search> support | | form | <form> (with name) | Forms without accessible name | | region | <section> (with name) | Generic labeled regions |

Common ARIA Attributes

| Attribute | Purpose | Example | |-----------|---------|---------| | aria-label | Invisible label for element | <button aria-label="Close dialog">X</button> | | aria-labelledby | Points to visible label element | <div aria-labelledby="heading-id"> | | aria-describedby | Points to descriptive text | <input aria-describedby="password-help"> | | aria-expanded | Toggle/disclosure state | <button aria-expanded="false">Menu</button> | | aria-hidden | Hide from assistive tech | <span aria-hidden="true">decorative icon</span> | | aria-live | Announce dynamic content | <div aria-live="polite">Status: Saved</div> | | aria-required | Field is required | <input aria-required="true"> (prefer required attr) | | aria-invalid | Field has validation error | <input aria-invalid="true"> | | aria-current | Current item in a set | <a aria-current="page">Home</a> | | aria-disabled | Disabled but focusable | <button aria-disabled="true">Submit</button> |

Live Regions

For content that updates dynamically (notifications, status messages, chat).

<!-- Polite: announced after current speech finishes -->
<div aria-live="polite" aria-atomic="true">
  3 items in your cart
</div>

<!-- Assertive: interrupts current speech (use sparingly) -->
<div aria-live="assertive" role="alert">
  Error: Payment failed. Please try again.
</div>

<!-- Status: polite + role=status (form feedback, progress) -->
<div role="status">
  Saving... Done!
</div>

| Politeness | When to Use | |------------|------------| | polite | Status updates, cart counts, non-urgent info | | assertive | Errors, warnings, time-sensitive alerts | | off | Disable announcements (default) |

Keyboard Navigation

Focus Management Rules

| Rule | Implementation | |------|---------------| | All interactive elements are focusable | Use native HTML elements or tabindex="0" | | Focus order matches visual order | Source order = visual order, avoid CSS reordering | | Focus is visible | Never outline: none without a visible alternative | | No keyboard traps | User can always Tab away (except modal dialogs) | | Skip links available | First focusable element skips to main content |

Skip Link Pattern

<!-- First element in <body>, visually hidden until focused -->
<a href="#main-content" class="skip-link">
  Skip to main content
</a>

<!-- ... navigation ... -->

<main id="main-content" tabindex="-1">
  <!-- Content starts here -->
</main>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: 8px 16px;
  background: #000;
  color: #fff;
  z-index: 100;
  transition: top 0.2s;
}

.skip-link:focus {
  top: 0;
}

Key Bindings Reference

| Pattern | Expected Keys | |---------|--------------| | Buttons | Enter or Space to activate | | Links | Enter to follow | | Checkboxes | Space to toggle | | Radio buttons | Arrow keys to move, Space to select | | Tabs | Arrow keys to switch, Tab to exit tab list | | Menus | Arrow keys to navigate, Enter to select, Escape to close | | Dialogs | Escape to close, Tab trapped inside, focus on close or first element | | Dropdowns | Arrow keys to navigate, Enter to select, Escape to close |

Tab Trap for Modals

function trapFocus(dialog) {
  const focusable = dialog.querySelectorAll(
    'a[href], button:not([disabled]), input:not([disabled]), ' +
    'select:not([disabled]), textarea:not([disabled]), [tabindex="0"]'
  );
  const first = focusable[0];
  const last = focusable[focusable.length - 1];

  dialog.addEventListener('keydown', (e) => {
    if (e.key !== 'Tab') return;

    if (e.shiftKey) {
      if (document.activeElement === first) {
        last.focus();
        e.preventDefault();
      }
    } else {
      if (document.activeElement === last) {
        first.focus();
        e.preventDefault();
      }
    }
  });

  first.focus();
}

Color Contrast Requirements

WCAG 2.1 AA Minimums

| Content Type | Minimum Ratio | Example | |-------------|--------------|---------| | Normal text (<18px / <14px bold) | 4.5:1 | #595959 on #FFFFFF = 7:1 | | Large text (>=18px / >=14px bold) | 3:1 | #767676 on #FFFFFF = 4.5:1 | | UI components & graphical objects | 3:1 | Borders, icons, focus indicators | | Decorative / logos | No requirement | Brand logos are exempt |

Testing Contrast

# Browser DevTools: Inspect element > Color picker shows ratio
# Chrome: Lighthouse > Accessibility audit
# Firefox: Accessibility Inspector > Check for issues

Do Not Rely on Color Alone

<!-- BAD: Color is the only indicator -->
<span style="color: red;">Error in this field</span>

<!-- GOOD: Color + icon + text -->
<span class="error">
  <svg aria-hidden="true"><!-- error icon --></svg>
  Error: Email address is required
</span>

<!-- BAD: Link distinguished only by color -->
<p>Read our <span style="color: blue;">terms of service</span></p>

<!-- GOOD: Link has underline (and color) -->
<p>Read our <a href="/terms">terms of service</a></p>

Form Accessibility

Labels and Instructions

Compartilhar X LinkedIn