Low hanging accessibility wins checklist
Keyboard & Focus
Check that all controls are reachable and usable with the keyboard.
- Can I Tab/Shift+Tab to all interactive elements in a logical order?
- Can I activate controls with Enter/Space (and Arrow keys where expected)?
- Is there a visible focus ring when I navigate via keyboard?
- Can I close menus/dialogs with Escape, and does focus return to the trigger?
- Does focus never get lost or trapped (except intentionally in modals)?
Semantics & Roles
Check that elements use the right HTML semantics so assistive tech understands them.
- Am I using the correct native element (
<button>
,<a href>
,<input>
) instead of adiv
/span
? - Does every input have a visible label that is programmatically associated?
- Do all link/button labels clearly describe their purpose (e.g., “Save changes” not “Click here”)?
- Do headings follow a logical order without skipping levels?
- Does the component have one — and only one — primary heading when it renders standalone (e.g., dialog/card title with
<h2>
)? - Am I using landmark elements where relevant (
<main>
,<nav>
,<header>
,<footer>
)?
Motion & Zoom
Check that the UI works for users with motion sensitivity or magnification needs.
- Does the component respect reduced motion when
prefers-reduced-motion
is enabled? - Can I zoom to 200% without layout breaking or forcing sideways scrolling?
Forms & State
Check that inputs, errors, and states are clearly labeled and communicated.
- Does every input have a visible, programmatically associated label?
- Are error or help messages placed near the field and tied with
aria-describedby
? - Are states (checked, disabled, pressed, loading) clearly reflected visually?
- Do buttons that trigger async actions show a loading or disabled state while processing?
- Do disabled buttons look visually disabled (dimmed, muted, etc.) without relying only on the
disabled
attribute?
Note: The disabled
attribute makes elements invisible to screen readers and not keyboard-focusable. Use aria-disabled="true"
for accessible inactive states.
Media & Images
Check that images and media are properly described or hidden when decorative.
Do all content images have an appropriate alt attribute?
If the
alt
is an empty string (alt=""
), does the surrounding text convey the image’s meaning so that no information is lost?Are decorative images/icons hidden with
alt=""
oraria-hidden="true"
?Do icons that convey meaning have a text label (or accessible name)?
Does media (video/audio) avoid auto-playing on load?
Use descriptive
alt
for meaningful images.Use
alt=""
for purely decorative images only when the surrounding text already conveys the meaning.
Note: The alt
attribute is required by the HTML spec on every <img>
tag.
Custom Controls
Check that custom UI components behave like their native equivalents.
- If I built a custom checkbox, radio, or switch, does it sync with a hidden native input?
- Do custom controls respond to Space/Enter like native elements?
Dialogs, Popovers, Tooltips
Check that overlays and popups are labeled, focusable, and dismissible.
- Does a modal set
aria-modal="true"
and trap focus while open? - Does a dialog, menu, or popover have a visible label or
aria-label
? - Do tooltips only provide supplemental info, not critical content?
ARIA Hygiene
Check that ARIA is used sparingly and correctly.
- Am I only using ARIA attributes when necessary?
- Are all ARIA attributes used valid and appropriate (
aria-expanded
only on toggles, etc.)? - Do elements avoid duplicate or conflicting labels?
Miscellaneous
Check that global attributes and temporary messages are handled accessibly.
- Do snackbars/toasts give users enough time to read or provide a way to dismiss them?
- Is the correct language attribute set (
lang="en"
, etc.)?
notes
This is not an exhaustie list and there many more things that can be done ensure that your site is accessibile. In my opinion this list is something that a dev can review and take care of relatively quickly without having to be knowledgeable in accessibility practices.
I left out the color contrast because it can be a little tricky to understand and test quickly. I also feel that in some organizations the devs may not have a say in this matter and a broader discussion it required to resolve it.