better-accessibility
Review and improve focus states, keyboard support, ARIA, forms, screen readers, hit areas, and motion accessibility.
Install
npx skills add https://github.com/jakubkrehel/skills --skill better-accessibilityHit areas
Target sizes, expanding hit areas without changing visual size, collision rules and drag alternatives.
Target sizes
Before reporting an undersized target, check the spacing, equivalent-control, inline, user-agent and essential exceptions.
Under the spacing exception, an undersized target passes when a 24px circle centered on its bounding box intersects no other target and no other undersized target's circle. In the simple case, 20px targets need a 4px gap.
The visible element can stay small; the hit area is what must be big. Anything that looks clickable must be clickable across its whole visual extent.
Expanding the hit area
Where the visible element is smaller, say a 20×20 checkbox, extend the hit area with a pseudo-element. Put it on the <label> wrapping the input or on the <button>, never on the <input>, because form controls don't render ::before/::after reliably. A wrapper that is not the input's <label> takes the click and toggles nothing.
CSS example
Tailwind example
Layout alternative
Where the element can afford real box size, skip the pseudo-element and let the box be the target:
Collision rule
Where the extended hit area overlaps another interactive element, shrink the pseudo-element to the largest size that does not collide.
Decorative layers
A decorative layer painted over interactive content absorbs every pointer event its box covers: a gradient scrim, a glow, a blurred sheen, a full-bleed ::after. The control underneath looks live and does nothing, and no hit-area sizing fixes it.
Give each one pointer-events: none (Tailwind pointer-events-none) so events reach the control below. A layer that is an element rather than a pseudo-element also gets aria-hidden="true":
Keep pointer events on any layer the user is meant to hit: a modal scrim that dismisses on click is a control, not decoration.
Gestures and dragging
- Every drag needs a single-pointer alternative under 2.5.7, such as move-up and move-down buttons on a sortable row, or a menu on a kanban card.
- Every multipoint or path-based gesture, such as a pinch or a swipe, needs a single-pointer alternative under 2.5.1.
- Set
touch-action: noneon a surface implementing its own pan, zoom or drag gestures, so the browser stops claiming them for scrolling and pinch-zoom. Scope it to that surface; at page level it removes scrolling.