better-accessibility

jakubkrehel/skills · Agent Skill

Review and improve focus states, keyboard support, ARIA, forms, screen readers, hit areas, and motion accessibility.

Jump to install ↓

Overview

PublisherjakubkrehelCommunity
Repositoryjakubkrehel/skills ↗
Skill folderbetter-accessibility
Stars8,643
Forks330
Bundled files8
LicenseMIT
Last updatedOctober 25, 2026
LinksSkill source ↗ · Repository ↗

Mozgi check

What we found in the skill files. Details come with a subscription.

Security
medium risk · 1 point needs attention
Compatibility
instructions only — works with most agents
Similar skills
31 similar skills found
Also with subscription

Installation

A skill is a folder with a SKILL.md file. Pick your agent and run the commands in a terminal (macOS, Linux or Git Bash on Windows) from your project root.

Copy the prompt into Claude, Codex or another assistant: it will review the skill and install it for you.

Install the “better-accessibility” skill from mozgi.io (https://mozgi.io/skills/jakubkrehel-better-accessibility/) for me.

1. Download the archive: https://mozgi.io/skills/jakubkrehel-better-accessibility/download
   If it fails, take the skill folder from the source: https://github.com/jakubkrehel/skills/tree/main/skills/better-accessibility
2. Read SKILL.md and the other files. Check the skill is safe: no hidden commands, no sending data elsewhere, no scripts doing something other than described. If anything looks suspicious, stop and tell me.
3. Put the “better-accessibility” folder into your agent's skills folder: .claude/skills/ for Claude Code, .agents/skills/ for Codex, .cursor/skills/ for Cursor, .gemini/skills/ for Gemini CLI. Inside the project if we are in one, otherwise in the home folder (~/.claude/skills/ etc.).
4. Make sure <skills folder>/better-accessibility/SKILL.md exists.
5. Briefly tell me what this skill does and offer to try it on my task.

If you cannot do a step yourself, tell me what to click or type.

Review the source files

8 files Download Zip

Read SKILL.md and any companion files before deciding whether to install. Click a file to preview it.

SKILL.md contents

Original author text · read-only

Accessibility

This skill reviews and fixes semantics, keyboard and focus behavior, accessible names, forms, announcements, motion and zoom. It reports each failure against the WCAG criterion it breaks and writes the fix in the project's styling system.

Reviewing means two walks. Keyboard-only, where every flow completes without a mouse. Then screen-reader, where every control announces a name, a role and its state. When unsure, take the platform default over a custom rebuild, and remove ARIA rather than add it.

Contrast measurement and color fixes belong to better-colors. Text sizing, iOS input zoom and language metadata belong to better-typography. Spacing between targets and spatial RTL belong to better-layout. Label, error and alt-text wording belong to better-writing. Animation recipes, hover styling and scroll containment belong to better-ui.

Criteria, not conventions

A finding cites a WCAG 2.2 Level A or AA criterion by number, or a concrete task an assistive-technology user cannot complete. Everything else is a recommendation and never HIGH. That covers AAA criteria, APG conventions, the one-<h1> and no-skipped-levels outline and the 44px and 40px targets. The criterion thresholds below are exact. The larger targets are heuristics, so keep an established, usable density.

Native elements first

The first rule of ARIA: don't use ARIA when a native element exists. <button> for actions, <a href> for navigation, never <div onClick>. A real link must support Cmd/Ctrl/middle-click. See semantics-and-aria.md ↗ for landmarks and button-vs-link.

Disabled means unavailable

Use native disabled when a control is genuinely unavailable. Reach for aria-disabled="true" only when it should stay focusable, then block pointer, keyboard and form behavior in code and style the state explicitly. The rules are in semantics-and-aria.md ↗.

Visible focus rings

Style :focus-visible, not bare :focus. Keyboard users get a ring and mouse users usually don't. Prefer the browser's unmodified indicator.

A custom ring needs a project focus token or another explicit color. It must reach 3:1 against every adjacent color it crosses, currentColor included, under 1.4.11. A 2px solid perimeter with a 3:1 change of contrast is the 2.4.13 AAA target. Never use outline: none without a verified replacement, and preserve system colors in forced-colors mode.

A focused element must never sit fully hidden behind a sticky header, footer or banner (2.4.11). Pad the scroller by the sticky chrome's height, a fix better-layout owns. Recipes are in focus-and-keyboard.md ↗.

Full keyboard support

Every pointer interaction needs a keyboard path. Follow the ARIA APG patterns: Escape closes overlays, arrow keys move within composite widgets, Tab moves between widgets, Enter and Space activate buttons.

Use only tabindex="0" to join the natural tab order and tabindex="-1" for programmatic focus. Positive values break that order. Composite widgets use roving tabindex, where the active item is 0 and every other is -1. Where focus must stay in an input, as in a combobox, use aria-activedescendant instead. Key maps per widget are in focus-and-keyboard.md ↗.

Trap and restore focus

Prefer <dialog> opened with showModal(), which makes the background inert and handles Escape. A custom overlay sets inert on the background, role="dialog" and aria-modal="true" on itself. Either way, move focus inside on open and return it to the trigger on close.

Client-side route changes reset nothing. Update document.title and move focus to the new view's <h1> or <main>. Both recipes are in focus-and-keyboard.md ↗.

Minimum hit area

WCAG 2.5.8's Level AA baseline is a 24×24 CSS-pixel target, or one of its exceptions. Aim for 44×44px on touch and 40×40px on desktop where density permits. Extend with a pseudo-element when the visible element should stay smaller.

Never let extended hit areas overlap. Give decorative layers pointer-events: none, so a glow never swallows the clicks meant for the control beneath it.

Every drag interaction needs a single-pointer alternative, such as buttons or a menu that reorder or move the same item (2.5.7). Sizes, exceptions and collision rules are in hit-areas.md ↗.

Label and type every control

Every input gets a <label for> or a wrapping <label>. A placeholder is never a label. Label and control share one hit target, with no dead zone between a checkbox and its text.

Add a valid autocomplete token and a descriptive name attribute, plus the type and inputmode that summon the right keyboard. Never block paste; users paste passwords and one-time codes. See forms.md ↗.

Errors that announce

Validate on submit, never by disabling submit until the form is valid. Mark failing fields aria-invalid="true", point aria-describedby at the inline error text and focus the first invalid field. Submit behavior while the request runs is in forms.md ↗.

Accessible names everywhere

Icon-only buttons need a descriptive aria-label. Visible label text must appear in the accessible name. Decorative elements get aria-hidden="true", never on a focusable element.

Pair color with a second cue

Status needs a redundant cue: an icon, text or an underline alongside the color (1.4.1).

This skill decides which contrast requirement applies:

| Criterion | Applies to | Minimum |

| --- | --- | --- |

| 1.4.3 AA | Text | 4.5:1 |

| 1.4.3 AA | Large text, at least 24px or 18.67px bold | 3:1 |

| 1.4.11 AA | UI component boundaries, states and meaningful graphics | 3:1 |

Inactive controls and logos are exempt. Use better-colors to measure the rendered pair. When it fails, report the pair and the criterion it misses, and leave the colors alone unless asked.

Honor prefers-reduced-motion

Wrap motion in @media (prefers-reduced-motion: no-preference) so it is opt-in. Under reduced motion, replace slides and scales with opacity cross-fades, and kill parallax and autoplay entirely. See motion-and-zoom.md ↗.

Nothing the user needs runs on a timer

Anything moving, blinking or updating on its own for more than 5 seconds needs a visible pause control (2.2.2). Toasts carrying an action or an error stay until dismissed. The rules are in motion-and-zoom.md ↗.

Announce dynamic content

Three mechanisms, three jobs. aria-describedby carries field-specific validation. A polite live region (role="status") carries non-urgent updates not tied to a control, such as toasts and result counts. role="alert" carries urgent untied errors and nothing else.

Repeated polite announcements need a stable empty region rendered before its text updates. Dynamically inserted alerts vary in support, so test them on the screen readers you target. See screen-readers.md ↗.

Alt text by purpose

Decorative images get alt="". Informative images describe the meaning. Functional images describe the action, never the picture. The full table is in screen-readers.md ↗.

Structure is navigation

Use headings that describe their sections and form a coherent outline. Expose one visible primary <main> landmark. When repeated navigation or chrome precedes it, make a "Skip to content" link the first focusable element. Anchored headings get scroll-margin-block-start.

Survive zoom and text resize

Text must survive 200% resize (1.4.4), and the page must reflow at 320px width without horizontal scrolling (1.4.10). Text containers take min-height, not height, and better-layout owns the rest of that fix. Never set maximum-scale=1 or user-scalable=no in the viewport meta. iOS input zoom is fixed with better-typography's 16px rule instead.

Before you finish

| Pattern | Fix |

| --- | --- |

| outline: none or outline-none with no focus-visible replacement nearby | Restore the browser ring or add a verified custom one |

| <div onClick or <span onClick | Use <button>, or <a href> when it navigates |

| role="button" or role="tab" with no onKeyDown | Use the native element, or implement the APG key map |

| tabIndex={1} or any positive tabindex | Fix the DOM order and use 0 |

| disabled={!isValid} on a submit button | Keep it enabled and validate on submit |

| {msg && <div role="status">, region mounted with its text | Render the empty region first and update its text |

| aria-live="assertive" on a success toast | role="status" |

| <img with no alt attribute | alt="" if decorative, otherwise describe the purpose |

| aria-label whose text omits the visible label | Start the name with the visible text |

| aria-hidden on an ancestor of a button, link or input | Remove it, or make the subtree inert |

| maximum-scale=1 or user-scalable=no | Remove it |

| Tooltip on a natively disabled control | Text beside it, or aria-disabled so it stays focusable |

| onDragStart or a drag library with no button alternative | Add a single-pointer path to the same result |

Reporting

Severity. HIGH prevents a task, hides content from assistive technology or creates a systemic failure. MEDIUM makes an interaction meaningfully harder. LOW is isolated polish. This domain's share of better-interface's escalation triggers is HIGH on sight. That is a missing accessible name, a missing focus indicator and a pointer path with no keyboard path. It is also motion ignoring reduced motion, loss at 320px or 200% and meaning carried by color alone.

Verification. Without a browser: accessible names on every interactive element, keyboard handlers on non-native controls, focus styles, prefers-reduced-motion guards and form labels bound to their inputs. With one: tab the flow in order, read computed names and roles from the accessibility tree, confirm a visible focus indicator at every stop and run an automated audit. Report every check you could not run as Not verified.

Format. Group findings under the principle each violates, ordered by severity, one row per root cause listing every location it appears in:

| Severity | Location | Before | After | Why |

| --- | --- | --- | --- | --- |

Location is path/to/file:line. Why names the WCAG criterion or principle and the user impact.

End with Block when any HIGH remains, Approve otherwise, leaving the rest in the table as work to do. Never Approve coverage you did not inspect. With nothing to report, state "No actionable accessibility findings" and report verification.

Frequently asked questions

What does the better-accessibility skill do?

Review and improve focus states, keyboard support, ARIA, forms, screen readers, hit areas, and motion accessibility.

How do I install better-accessibility?

Open the “Installation” block on this page and pick your agent — Claude Code, Codex, Cursor or Gemini CLI — for ready-made commands that copy the skill folder to the right place. Or copy the prompt from the “Via assistant” tab and let the assistant review and install the skill.

Which AI models work with better-accessibility?

Skills are plain Markdown instructions (the Agent Skills format), so better-accessibility works with any agent that reads SKILL.md: Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and more. The model loads the instructions only when a task matches the skill's description.

Is better-accessibility free?

The skill is published openly by jakubkrehel under the MIT license. The skill itself costs nothing — you only pay your AI provider for the tokens you use.

Is it safe to install skills?

A skill is a set of instructions your agent will follow, so read SKILL.md and its companion files before installing. Scripts in the skill folder only run if your agent runs them — keep an eye on what it does and do not grant unnecessary permissions.

How is a skill different from an MCP server or a plugin?

An MCP server or plugin gives the model new tools — code that runs and returns a result. A skill gives it knowledge and process: how to approach a task, which steps to follow and what good output looks like. It needs no server or API key.

Related skills

All skills →
better-colors OKLCH color space for web projects. Convert hex/rgb/hsl to oklch, generate palettes, check contrast, handle gamut boundaries, and theme with Tailwind v4. Triggers on oklch, color conversion, palette generation, contrast ratio, gamut, display p3, design tokens, hue drift, chroma, dark mode colors. jakubkrehel8.6k better-interface Run a holistic interface review across accessibility, layout, writing, typography, color, and visual polish. jakubkrehel8.6k better-typography Web typography from choosing fonts to spacing, wrapping and accessibility. Use when picking or pairing typefaces, configuring variable fonts or OpenType features, setting up a type scale, styling text in components, truncating text, styling underlines, selection, placeholders or carets, or reviewing frontend code for typography. Triggers on typography, fonts, font formats, woff2, variable fonts, font-weight, opentype, font-feature-settings, letter-spacing, line-height, type scale, tabular numbers, text-wrap, truncation, line clamp, underlines, text-decoration, text selection, iOS input zoom, font smoothing, text contrast, measure, line length, text-box, smart punctuation, drop cap. jakubkrehel8.6k better-writing Improve UX writing for interface labels, errors, empty states, settings, notifications, and product voice consistency. jakubkrehel8.6k oklch-skill Practical OKLCH color workflow skill for building consistent, accessible, and tunable color systems in modern UIs. jakubkrehel frontend-ui-engineering Frontend UI engineering guidance covering component architecture, responsive design, accessibility, and maintainable implementation patterns. addyosmani111k