squirrelscan
GitHub

Accessibility audit rules: WCAG and ARIA checks

Audit rules for accessibility: accessible names, ARIA roles and attributes, forms, headings and landmarks, tables, language and zoom on every crawled page.

squirrelscan runs its accessibility rules against every page it crawls. They cover accessible names for buttons, links and form controls, ARIA roles and attributes, heading and landmark structure, tables, language declarations and viewport settings. Each page below quotes the exact report message a rule emits, and most findings identify the offending element by selector, id or quoted text, so a coding agent can go straight to the markup that needs changing.

Run only these rules

squirrel audit https://example.com --rule-include a11y

Where to start

These carry the highest severity and weight in the category.

Rules

RuleWhat it flagsSeverityScope
Accessible name for a meter element and role=meterA gauge that announces only a number tells a screen reader user nothing. squirrel checks native meter elements and role=meter.errorPer-page
Accessible name for a progress bar and role=progressbarA progress bar with no name announces a percentage and nothing else. squirrel checks native progress elements and role=progressbar.errorPer-page
Accessible names for buttons: what counts and how to checkA button with only an icon has no name for a screen reader. squirrel lists every button on every page that has nothing to announce.errorPer-page
accesskey: why duplicate shortcuts break and how to checkTwo elements claiming the same accesskey means one shortcut is unreachable. squirrel lists every duplicated access key on every page.warningPer-page
ARIA attributes that are not allowed on an elementrole=presentation with an aria-label, or a decorative image with one, contradicts itself. squirrel reports both on every page.warningPer-page
ARIA references pointing at duplicate or missing idsaria-labelledby resolving to two elements, or to none, names the wrong thing silently. squirrel checks all eight ARIA id references.errorPer-page
ARIA roles that require a particular parent rolerole=listitem outside a list, or a tab outside a tablist, loses its meaning. squirrel checks explicit roles and native li, tr, td and option.errorPer-page
ARIA roles that require particular child rolesrole=list with no listitem, or role=tablist with no tab, is an incomplete widget. squirrel checks thirteen container roles for their children.errorPer-page
aria-hidden on body or html: what it breaksaria-hidden=true on the body or html element asks assistive technology to ignore the entire page. squirrel checks both, at the highest weight.errorPer-page
aria-label: which elements need one and how to checkButtons, links and inputs with no visible text and no aria-label have no name for screen readers. squirrel finds every one on every page.errorPer-page
autocomplete: the right token for every form fieldName, email, address and payment fields with a missing or wrong autocomplete token break autofill. squirrel finds every one on every page.warningPer-page
Checkboxes, radios and switches with no accessible nameA checkbox that announces only its role gives no reason to tick it. squirrel checks toggle roles and native checkbox and radio inputs.errorPer-page
Color contrast: the 4.5:1 rule and how to check itLight gray text on white fails WCAG AA. squirrel measures the contrast of text whose color and background are both set inline, and reports pairs under 4.5:1.warningPer-page
Command roles: buttons, links and menu items need namesAnything that performs an action has to announce what it does. squirrel lists every command element on a page with no accessible name.errorPer-page
Definition list structure: what belongs inside a dlA stray paragraph between the terms of a dl breaks the pairing screen readers rely on. squirrel checks every definition list on the page.errorPer-page
Deprecated and abstract ARIA roles, and what to use insteadrole=directory is deprecated and abstract roles were never meant for markup. squirrel names every one it finds and its replacement.errorPer-page
Dialog accessible name: role=dialog and the dialog elementA modal with no name leaves screen reader users guessing what just opened. squirrel checks ARIA dialogs and native dialogs separately.errorPer-page
Dropdowns with no accessible name: naming a selectA select announced only as ‘combo box’ gives no clue what it changes. squirrel checks every select element on the page.errorPer-page
dt and dd outside a dl: orphaned definition list itemsA dt or dd that is not inside a dl loses the term-description pairing entirely. squirrel finds every orphan on every page.errorPer-page
Duplicate id on a focusable element: what it breaksTwo inputs sharing an id break label association and focus management. squirrel checks every focusable element that carries an id.errorPer-page
Empty headings: what counts as empty and how to checkA heading with no text still shows up in the screen reader outline, as a blank entry. squirrel flags every one on every page.warningPer-page
focus-visible: keeping a visible keyboard focus ringRemoving the focus outline leaves keyboard users with no idea where they are. squirrel flags outline:none with no :focus-visible fallback.warningPer-page
Focusable elements inside aria-hidden: the tab trapA hidden element that still takes focus lets keyboard users tab into nothing. squirrel finds them, and tells anti-spam honeypots apart.errorPer-page
Form labels: which inputs need one and how to checkAn input labelled only by its placeholder loses its label the moment someone types. squirrel lists every unlabeled input, textarea and select.errorPer-page
Heading order: why skipping from h1 to h3 mattersScreen reader users navigate by heading level, and a skipped level makes the outline harder to follow. squirrel checks document order on every page.warningPer-page
html lang: valid values and what a missing one breaksWithout a lang attribute a screen reader guesses the pronunciation, often wrongly. squirrel checks the html element on every page.errorPer-page
Identical link text pointing at different pagesTwo links reading ‘Learn more’ that go to different places are indistinguishable in a screen reader’s link list. squirrel finds them.warningPer-page
iframe title: naming embedded frames for screen readersAn iframe with no title is announced as just ‘frame’. squirrel checks every iframe and frame element on the page.errorPer-page
Input fields with no accessible name, ARIA and nativeText boxes, comboboxes and sliders that announce nothing. squirrel checks the nine ARIA input roles alongside native inputs and selects.errorPer-page
Input type, enterkeyhint and novalidate on formstype=text where type=email belongs costs mobile users the right keyboard. squirrel checks three ways a form opts out of browser help.warningPer-page
input type=image without alt: an unnamed submit buttonAn image input is a submit button drawn as a picture, and with no alt it announces nothing. squirrel checks every one on the page.errorPer-page
Inputs that block paste, and why that fails usersBlocking paste forces people to retype passwords by hand. squirrel finds onpaste, oncopy and oncut handlers that cancel the event.warningPer-page
Invalid ARIA attribute values and the types they needaria-checked=yes and aria-level=two are ignored by browsers. squirrel type-checks 26 ARIA attributes against their allowed values.errorPer-page
Invalid ARIA role values and how to check themA misspelled or invented role gives an element no semantics at all. squirrel validates every role attribute against the ARIA vocabulary.errorPer-page
Invalid aria-* attribute names, aria-labeledby includedA misspelled ARIA attribute is ignored by every browser and warns nobody. squirrel checks each aria-* name against the ARIA vocabulary.errorPer-page
Landmark regions: main, nav and footer on every pageScreen reader users jump between landmarks instead of reading top to bottom. squirrel reports which of the three a page has.infoPer-page
lang and xml:lang disagreeing on the html elementWhen both attributes are present and name different languages, a screen reader can pick the wrong voice. squirrel compares them.errorPer-page
lang on elements below html: validating every tagA quoted passage marked with a bad lang tag is read in the wrong voice. squirrel validates every lang attribute except the one on html.warningPer-page
Link text: why ‘click here’ fails and what to useLinks reading ‘click here’, and links wrapping an unlabeled icon, give screen reader users nothing to go on. squirrel lists both kinds.warningPer-page
Links in a paragraph told apart by color aloneA link inside body text needs more than color to be visible. squirrel flags links whose markup removes the underline.warningPer-page
meta http-equiv=refresh: redirects and auto-refreshA timed redirect moves the page out from under a screen reader user mid-sentence. squirrel reads the content value and grades it.errorPer-page
object elements with no alternative contentAn embedded object with no fallback is announced as nothing at all. squirrel checks every object element on the page.warningPer-page
One control, two labels: why multiple labels confuseA control with two labels is announced inconsistently across screen readers. squirrel counts the labels on every input on the page.warningPer-page
One main landmark per page, and what happens withoutA page with no main landmark, or with two, breaks the jump-to-content shortcut screen reader users rely on. squirrel counts them.warningPer-page
Orphaned li: list items outside ul, ol or menuAn li whose parent is not a list is announced as a plain block of text. squirrel checks the immediate parent of every list item.errorPer-page
Positive tabindex and why it breaks the tab ordertabindex=1 pulls an element to the front of the tab order for the entire page. squirrel flags every positive value on every page.warningPer-page
Redundant alt text: image of, filenames and captionsScreen readers already announce that it is an image, so alt starting with ‘photo of’ wastes the announcement. squirrel checks four ways.warningPer-page
Required ARIA attributes for a role, and what is missingrole=checkbox with no aria-checked has a state screen readers cannot read. squirrel checks the roles whose attributes are mandatory.errorPer-page
role=text with focusable children: why it breaksrole=text flattens a subtree into one announced string, so a link inside it cannot be operated. squirrel reports every case it finds.warningPer-page
role=tooltip with no content: what to checkA tooltip with nothing to announce leaves the control it explains unexplained. squirrel checks every role=tooltip element on the page.errorPer-page
role=treeitem: naming every node in a treeA tree node that announces only its position in the tree is unusable. squirrel checks every role=treeitem for something to read out.errorPer-page
Skip to content: bypassing repeated navigationKeyboard users tab through the whole navigation on every page without a bypass. squirrel accepts a skip link or landmark structure.warningPer-page
Table headers: why a data table needs th cellsA table built from styled td cells has no header relationships for a screen reader. squirrel checks every data table for th elements.warningPer-page
Tables sharing a name, and tables with noneSeveral tables on one page need distinct names or a screen reader’s table list is unusable. squirrel checks captions and labels.warningPer-page
td headers attribute pointing at a missing th idA headers attribute naming an id that does not exist leaves the cell unassociated. squirrel checks every reference in every table.errorPer-page
th cells with no data cells: a layout table in disguiseA header with no data in its row or column usually means the table is really a layout. squirrel builds the grid and checks each one.warningPer-page
Touch target size: the 24 and 44 pixel minimumsButtons and links smaller than a fingertip are hard to hit on a phone. squirrel flags interactive elements sized below 44 pixels inline.warningPer-page
ul and ol with children that are not list itemsA div between the li elements of a list changes what a screen reader announces. squirrel checks the direct children of every list.errorPer-page
user-scalable=no: viewport settings that block zoomA viewport that caps the zoom level stops low-vision users enlarging text. squirrel parses the viewport meta tag on every page.errorPer-page
Video captions: track elements and embedded playersA video with no caption track excludes deaf and hard of hearing viewers. squirrel checks native video and flags third-party embeds.warningPer-page
Visible label missing from the accessible nameA button showing ‘Search’ with aria-label ‘Find products’ may not respond when a user speaks its visible label. squirrel compares the two.errorPer-page

Key terms

  • Accessible name: The name assistive technology announces for an element, computed from its content, label, aria-label or aria-labelledby.
  • Alt text: The alt attribute that gives an image a text alternative for screen readers, failed loads and search engines.
  • Anchor text: The visible, clickable text of a link, which tells readers and search engines what the target is about.
  • ARIA: Accessible Rich Internet Applications: roles, states and properties that describe custom widgets to assistive technology.
  • Captions: Synchronised text of a video’s dialogue and sounds, supplied as a <track kind="captions"> file.
  • Client-side redirect: A redirect done in the page (meta refresh or JavaScript) rather than with an HTTP 3xx response.
  • Color contrast ratio: The luminance ratio between text and its background; WCAG AA asks for 4.5:1 for body text and 3:1 for large text.
  • Form labels: The <label> or accessible name tied to each form control, plus autocomplete tokens, so people know what to enter.
  • Heading hierarchy: The nesting of h1 to h6 headings that gives a page its outline for readers, screen readers and parsers.
  • Keyboard accessibility: Whether every control can be reached and used with a keyboard alone, with a visible focus indicator and sensible tab order.
  • Landmark regions: The page regions (main, nav, header, footer) that screen reader users jump between, plus the skip link to main content.
  • lang attribute: The lang attribute on <html> (and on passages) that declares the language, so screen readers pick the right voice.
  • Touch target size: The tappable area of a control; WCAG 2.2 sets 24 by 24 CSS pixels as the AA minimum.
  • Viewport meta tag: <meta name="viewport"> that sets the layout width to the device width; disabling zoom in it fails accessibility.
  • WCAG: The W3C’s Web Content Accessibility Guidelines, organised as testable success criteria at levels A, AA and AAA; 2.2 is current.

Images checks that every image has an alt attribute. Mobile checks tap targets, font size and the viewport tag from the phone side, and Content checks the heading outline of each page.

Learn more

Disable all Accessibility rules

[rules]
disable = ["a11y/*"]

Type to search…

↑↓ navigate↵ openesc close