tiny-a11y

Write as little code as possible. Use native HTML elements that are already accessible instead of adding ARIA attributes to generic elements.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "tiny-a11y" with this command: npx skills add mikemai2awesome/agent-skills/mikemai2awesome-agent-skills-tiny-a11y

Tiny A11y

Write as little code as possible. Use native HTML elements that are already accessible instead of adding ARIA attributes to generic elements.

Core Principles

  • Trust the browser — Native elements have built-in accessibility

  • Semantic over ARIA — Use the right element, not role attributes

  • Less is more — Every ARIA attribute you don't write is one less thing to break

  • Native first — Use <dialog> , <details> , <button> before reaching for JavaScript

References

  • Use WCAG 2.2 Understanding for accessibility guidance

  • Use WAI-ARIA 1.2 for ARIA attributes

  • Use APG Gherkin for component test cases

  • Use Design Tokens for design systems terminology

HTML Guidelines

Use Native Elements

The browser already provides accessible elements. Use them.

<!-- Don't do this — too much code --> <div role="button" tabindex="0" onclick="submit()">Submit</div>

<!-- Do this — native button is already accessible --> <button type="submit">Submit</button>

Don't Add Redundant Roles

Landmark elements already have implicit roles. Don't repeat them.

<!-- Don't do this --> <header role="banner">...</header> <nav role="navigation">...</nav> <main role="main">...</main> <footer role="contentinfo">...</footer>

<!-- Do nothing — the browser already handles this --> <header>...</header> <nav>...</nav> <main>...</main> <footer>...</footer>

Use Semantic Elements Over Divs

Replace generic containers with meaningful elements.

<!-- Don't do this --> <div class="header"> <div class="nav">...</div> </div>

<!-- Do this --> <header> <nav>...</nav> </header>

Skip the Title Attribute

The title attribute is poorly supported. Only use it on <iframe> .

<!-- Don't do this --> <button title="Submit form">Submit</button>

<!-- Only use title on iframe --> <iframe src="..." title="Video player"></iframe>

Component Patterns

Use native elements that already have the behavior you need.

Accordion

Use native <details> and <summary> . No JavaScript needed.

<!-- Don't do this — too much code --> <div class="accordion"> <button aria-expanded="false" aria-controls="panel-1">Section</button> <div id="panel-1" hidden>Content</div> </div>

<!-- Do this — zero JavaScript required --> <details> <summary>Section</summary> <p>Content</p> </details>

Modal Dialog

Use native <dialog> with showModal() . Focus trapping and Escape key handling are built-in.

<!-- Don't do this — requires focus trap JavaScript --> <div role="dialog" aria-modal="true" aria-labelledby="title"> <h2 id="title">Title</h2> <p>Content</p> </div>

<!-- Do this — focus trap is automatic --> <dialog id="my-dialog"> <h2>Title</h2> <p>Content</p> <button type="button" onclick="this.closest('dialog').close()">Close</button> </dialog>

<button type="button" onclick="document.getElementById('my-dialog').showModal()"

Open dialog </button>

The showModal() method automatically:

  • Traps focus inside the dialog

  • Closes on Escape key

  • Adds the ::backdrop pseudo-element

  • Marks content behind as inert

Navigation

Use <nav> with <button> and aria-expanded for dropdowns.

<nav> <ul> <li> <button aria-expanded="false" aria-controls="submenu">Products</button> <ul id="submenu" hidden> <li><a href="/product-1">Product 1</a></li> </ul> </li> </ul> </nav>

Don't use role="menu" , role="menuitem" , or aria-haspopup for navigation.

Alert

A single role="alert" is all you need.

<div role="alert">Your changes have been saved.</div>

Other Patterns

When native elements aren't enough, follow these APG patterns:

  • Feed Pattern for infinite scroll

  • Combobox with Autocomplete for custom selects

  • Switch Button Pattern for toggles

  • Manual Tabs Pattern for tabs

  • WAI Carousel Tutorial for carousels

CSS Guidelines

Use OKLCH for Colors

OKLCH provides a wider color gamut and perceptually uniform lightness.

:root { --color-primary: oklch(50% 0.2 260); --color-surface: oklch(98% 0 0); }

Use Relative Units

Use rem , em , % , vw , vh instead of px , except for borders.

/* Don't do this */ .card { padding: 16px; font-size: 14px; }

/* Do this */ .card { padding: 1rem; font-size: 0.875rem; }

Use Logical Properties

Support all languages and writing directions.

/* Don't do this */ .card { margin-left: 1rem; padding-top: 2rem; width: 20rem; }

/* Do this */ .card { margin-inline-start: 1rem; padding-block-start: 2rem; inline-size: 20rem; }

Use Cascade Layers

Organize CSS in this order: @layer config, resets, components, utilities .

@layer config, resets, components, utilities;

@layer config { :root { --color-primary: oklch(50% 0.2 260); } }

@layer resets { /* CSS resets */ }

@layer components { .c-button { /* component styles */ } }

@layer utilities { .u-visually-hidden { /* utility styles */ } }

Use Class Prefixes

  • c- for component classes

  • u- for utility classes

  • js- for JavaScript selectors

<div class="c-card js-accordion">...</div>

Use ARIA Attributes as Styling Hooks

Don't create modifier classes when ARIA attributes already exist.

/* Don't do this — extra classes */ .accordion-header--collapsed { } .accordion-header--expanded { }

/* Do this — style the ARIA state */ [aria-expanded="false"] { } [aria-expanded="true"] { }

More examples:

[aria-current="page"] { font-weight: bold; } [aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; } [aria-selected="true"] { background-color: highlight; } [aria-invalid="true"] { border-color: red; }

Use Focus-Visible

Only show focus rings when needed.

/* Don't do this — shows ring on click */ button:focus { outline: 2px solid; }

/* Do this — only shows ring for keyboard users */ button:focus-visible { outline: 2px solid; outline-offset: 2px; }

Respect Motion Preferences

Only animate when the user allows it.

@media (prefers-reduced-motion: no-preference) { .animated { transition: transform 0.3s ease; } }

Don't Write All Caps in HTML

Use CSS instead so screen readers don't spell out letters.

<!-- Don't do this --> <span>SUBMIT</span>

<!-- Do this --> <span class="u-uppercase">Submit</span>

.u-uppercase { text-transform: uppercase; }

JavaScript Guidelines

  • Use vanilla JavaScript only

  • Don't use component libraries (Radix, Shadcn)

  • Don't use utility frameworks (Tailwind CSS)

Quick Reference

Instead of Use

<div role="button">

<button>

<div role="dialog">

<dialog>

<div role="navigation">

<nav>

<div role="banner">

<header>

<div role="main">

<main>

<div role="contentinfo">

<footer>

Custom accordion JS <details>

  • <summary>

Focus trap library Native <dialog>

.is-expanded class [aria-expanded="true"]

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

tiny-css

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

vercel-react-best-practices

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

Repository Source
213.6K23Kvercel
Coding

svelte5-best-practices

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

apify-actor-development

No summary provided by upstream source.

Repository SourceNeeds Review
2.1K-apify