Scan rules and severity
Severity categories
Oobee groups every issue into one of three categories. Refer to Read and export scan reports for how the report shows them.
| Category | Meaning |
|---|---|
| Must Fix | WCAG Level A and AA success criteria, except results that need review |
| Good to Fix | WCAG Level AAA success criteria and best-practice rules that are accepted practice but do not map to a WCAG criterion |
| Manual Review Required | Results that may be false positives and need a person to confirm. The CSV and JSON files call this category needsReview. |
Level AAA rules are off by default. Turn them on with -y enable-wcag-aaa on the CLI or the enable-wcag-aaa ruleset in the npm module. The disable-oobee ruleset removes Oobee’s own checks, whose rule IDs start with oobee-, and runs axe-core rules only. Refer to CLI options, environment variables and error codes for the -y option.
WCAG levels
| Level | Meaning |
|---|---|
| A | The minimum level, addressing the most critical issues |
| AA | Builds on Level A. The standard most organisations aim for |
| AAA | The highest level, with stricter requirements. It is often not practical to meet for all content |
Oobee rules map to WCAG 2.0, 2.1 and 2.2 criteria. Oobee reports results against WCAG 2.2.
Criteria and DSS clauses
Each WCAG criterion that Oobee checks maps to a clause in the Singapore Government Digital Service Standards (DSS) Control Catalog. The clause prefixes are WP (Perceivable), WO (Operable), WU (Understandable) and WR (Robust). Level AAA criteria have no named DSS clause.
| WCAG criterion | DSS clause | Level | Category |
|---|---|---|---|
| 1.1.1 | WP-1 | A | Must Fix |
| 1.2.2 | WP-2 | A | Must Fix |
| 1.3.1 | WP-6 | A | Must Fix |
| 1.3.5 | WP-10 | AA | Must Fix |
| 1.4.1 | WP-11 | A | Must Fix |
| 1.4.2 | WP-12 | A | Must Fix |
| 1.4.3 | WP-13 | AA | Must Fix |
| 1.4.4 | WP-14 | AA | Must Fix |
| 1.4.6 | None | AAA | Good to Fix |
| 1.4.12 | WP-18 | AA | Must Fix |
| 2.1.1 | WO-1 | A | Must Fix |
| 2.1.3 | None | AAA | Must Fix (see the note below the table) |
| 2.2.1 | WO-4 | A | Must Fix |
| 2.2.2 | WO-5 | A | Must Fix |
| 2.2.4 | None | AAA | Good to Fix |
| 2.4.1 | WO-7 | A | Must Fix |
| 2.4.2 | WO-8 | A | Must Fix |
| 2.4.4 | WO-10 | A | Must Fix |
| 2.4.9 | None | AAA | Good to Fix |
| 2.5.8 | WO-18 | AA | Must Fix |
| 3.1.1 | WU-1 | A | Must Fix |
| 3.1.2 | WU-2 | AA | Must Fix |
| 3.1.5 | None | AAA | Manual Review Required |
| 3.2.5 | None | AAA | Good to Fix |
| 3.3.2 | WO-12 | A | Must Fix |
| 4.1.2 | WR-1 | A | Must Fix |
| Best practice | None | None | Good to Fix |
Criterion 2.1.3 is checked by the rule scrollable-region-focusable, which is a Must Fix rule for criterion 2.1.1.
WCAG 2.0 Level A rules
| Rule ID | Description | Severity | WCAG | DSS |
|---|---|---|---|---|
area-alt |
Ensures <area> elements of image maps have alternate text |
Must Fix | 2.4.4, 4.1.2 | WO-10, WR-1 |
aria-allowed-attr |
Ensures an element’s role supports its ARIA attributes | Must Fix | 4.1.2 | WR-1 |
aria-braille-equivalent |
Ensures aria-braillelabel and aria-brailleroledescription have a non-braille equivalent |
Must Fix | 4.1.2 | WR-1 |
aria-command-name |
Ensures every ARIA button, link and menuitem has an accessible name | Must Fix | 4.1.2 | WR-1 |
aria-conditional-attr |
Ensures ARIA attributes are used as described in the specification of the element’s role | Must Fix | 4.1.2 | WR-1 |
aria-deprecated-role |
Ensures elements do not use deprecated roles | Must Fix | 4.1.2 | WR-1 |
aria-hidden-body |
Ensures aria-hidden="true" is not present on the document body |
Must Fix | 4.1.2 | WR-1 |
aria-hidden-focus |
Ensures aria-hidden elements are not focusable and do not contain focusable elements |
Must Fix | 4.1.2 | WR-1 |
aria-input-field-name |
Ensures every ARIA input field has an accessible name | Must Fix | 4.1.2 | WR-1 |
aria-meter-name |
Ensures every ARIA meter node has an accessible name | Must Fix | 1.1.1 | WP-1 |
aria-progressbar-name |
Ensures every ARIA progressbar node has an accessible name | Must Fix | 1.1.1 | WP-1 |
aria-prohibited-attr |
Ensures ARIA attributes are not prohibited for an element’s role | Must Fix | 4.1.2 | WR-1 |
aria-required-attr |
Ensures elements with ARIA roles have all required ARIA attributes | Must Fix | 4.1.2 | WR-1 |
aria-required-children |
Ensures elements with an ARIA role that requires child roles contain them | Must Fix | 1.3.1 | WP-6 |
aria-required-parent |
Ensures elements with an ARIA role that requires parent roles are contained by them | Must Fix | 1.3.1 | WP-6 |
aria-roles |
Ensures all elements with a role attribute use a valid value | Must Fix | 4.1.2 | WR-1 |
aria-toggle-field-name |
Ensures every ARIA toggle field has an accessible name | Must Fix | 4.1.2 | WR-1 |
aria-tooltip-name |
Ensures every ARIA tooltip node has an accessible name | Must Fix | 4.1.2 | WR-1 |
aria-valid-attr-value |
Ensures all ARIA attributes have valid values | Must Fix | 4.1.2 | WR-1 |
aria-valid-attr |
Ensures attributes that begin with aria- are valid ARIA attributes |
Must Fix | 4.1.2 | WR-1 |
blink |
Ensures <blink> elements are not used |
Must Fix | 2.2.2 | WO-5 |
button-name |
Ensures buttons have discernible text | Must Fix | 4.1.2 | WR-1 |
bypass |
Ensures each page has at least one mechanism to bypass navigation and jump to the content | Must Fix | 2.4.1 | WO-7 |
definition-list |
Ensures <dl> elements are structured correctly |
Must Fix | 1.3.1 | WP-6 |
dlitem |
Ensures <dt> and <dd> elements are contained by a <dl> |
Must Fix | 1.3.1 | WP-6 |
document-title |
Ensures each HTML document contains a non-empty <title> element |
Must Fix | 2.4.2 | WO-8 |
duplicate-id-aria |
Ensures every id value used in ARIA and in labels is unique |
Must Fix | 4.1.2 | WR-1 |
form-field-multiple-labels |
Ensures a form field does not have multiple label elements | Must Fix | 3.3.2 | WO-12 |
frame-focusable-content |
Ensures <frame> and <iframe> elements with focusable content do not have tabindex=-1 |
Must Fix | 2.1.1 | WO-1 |
frame-title-unique |
Ensures <iframe> and <frame> elements contain a unique title attribute |
Must Fix | 4.1.2 | WR-1 |
frame-title |
Ensures <iframe> and <frame> elements have an accessible name |
Must Fix | 4.1.2 | WR-1 |
html-has-lang |
Ensures every HTML document has a lang attribute |
Must Fix | 3.1.1 | WU-1 |
html-lang-valid |
Ensures the lang attribute of the <html> element has a valid value |
Must Fix | 3.1.1 | WU-1 |
html-xml-lang-mismatch |
Ensures HTML elements with both valid lang and xml:lang attributes agree on the base language |
Must Fix | 3.1.1 | WU-1 |
image-alt |
Ensures <img> elements have alternate text or a role of none or presentation |
Must Fix | 1.1.1 | WP-1 |
input-button-name |
Ensures input buttons have discernible text | Must Fix | 4.1.2 | WR-1 |
input-image-alt |
Ensures <input type="image"> elements have alternate text |
Must Fix | 1.1.1, 4.1.2 | WP-1, WR-1 |
label |
Ensures every form element has a label | Must Fix | 4.1.2 | WR-1 |
link-in-text-block |
Ensures links are distinguished from surrounding text in a way that does not rely on colour | Must Fix | 1.4.1 | WP-11 |
link-name |
Ensures links have discernible text | Must Fix | 2.4.4, 4.1.2 | WO-10, WR-1 |
list |
Ensures lists are structured correctly | Must Fix | 1.3.1 | WP-6 |
listitem |
Ensures <li> elements are used semantically |
Must Fix | 1.3.1 | WP-6 |
marquee |
Ensures <marquee> elements are not used |
Must Fix | 2.2.2 | WO-5 |
meta-refresh |
Ensures <meta http-equiv="refresh"> is not used for delayed refresh |
Must Fix | 2.2.1 | WO-4 |
nested-interactive |
Ensures interactive controls are not nested, because screen readers may not announce them and they can cause focus problems | Must Fix | 4.1.2 | WR-1 |
no-autoplay-audio |
Ensures <video> or <audio> elements do not autoplay audio for more than 3 seconds without a control to stop or mute it |
Must Fix | 1.4.2 | WP-12 |
object-alt |
Ensures <object> elements have alternate text |
Must Fix | 1.1.1 | WP-1 |
role-img-alt |
Ensures [role="img"] elements have alternate text |
Must Fix | 1.1.1 | WP-1 |
scrollable-region-focusable |
Ensures elements with scrollable content are accessible by keyboard | Must Fix | 2.1.1, 2.1.3 | WO-1 |
select-name |
Ensures <select> elements have an accessible name |
Must Fix | 4.1.2 | WR-1 |
server-side-image-map |
Ensures server-side image maps are not used | Must Fix | 2.1.1 | WO-1 |
svg-img-alt |
Ensures <svg> elements with an img, graphics-document or graphics-symbol role have accessible text |
Must Fix | 1.1.1 | WP-1 |
td-headers-attr |
Ensures each cell in a table that uses the headers attribute refers only to other cells in that table |
Must Fix | 1.3.1 | WP-6 |
th-has-data-cells |
Ensures <th> elements and elements with role=columnheader or role=rowheader have data cells they describe |
Must Fix | 1.3.1 | WP-6 |
video-caption |
Ensures <video> elements have captions |
Must Fix | 1.2.2 | WP-2 |
summary-name |
Ensures <summary> elements have discernible text |
Must Fix | 4.1.2 | WR-1 |
oobee-confusing-alt-text |
Flags image alternative text of “img”, “image”, “picture”, “photo” or “graphic”, which is confusing or not useful | Must Fix | 1.1.1 | WP-1 |
oobee-accessible-label |
Ensures clickable elements (elements with mouse-click interaction) have accessible labels | Must Fix | 2.1.1, 4.1.2 | WO-1, WR-1 |
WCAG 2.0 Level AA rules
| Rule ID | Description | Severity | WCAG | DSS |
|---|---|---|---|---|
color-contrast |
Ensures the contrast between foreground and background colours meets the WCAG 2 AA minimum contrast ratio thresholds | Must Fix | 1.4.3 | WP-13 |
meta-viewport |
Ensures <meta name="viewport"> does not disable text scaling and zooming |
Must Fix | 1.4.4 | WP-14 |
valid-lang |
Ensures lang attributes have valid values |
Must Fix | 3.1.2 | WU-2 |
WCAG 2.1 and 2.2 Level AA rules
| Rule ID | Description | Severity | WCAG | DSS |
|---|---|---|---|---|
autocomplete-valid |
Ensures the autocomplete attribute is correct and suitable for the form field |
Must Fix | 1.3.5 | WP-10 |
avoid-inline-spacing |
Ensures text spacing set through style attributes can be adjusted with custom stylesheets | Must Fix | 1.4.12 | WP-18 |
target-size |
Ensures touch targets have sufficient size and space | Must Fix | 2.5.8 | WO-18 |
WCAG Level AAA rules
These rules run only when AAA rules are enabled.
| Rule ID | Description | Severity | WCAG | DSS |
|---|---|---|---|---|
color-contrast-enhanced |
Ensures the contrast between foreground and background colours meets the WCAG 2 AAA enhanced contrast ratio thresholds | Good to Fix | 1.4.6 | None |
identical-links-same-purpose |
Ensures links with the same accessible name serve a similar purpose | Good to Fix | 2.4.9 | None |
meta-refresh-no-exceptions |
Ensures <meta http-equiv="refresh"> is not used for delayed refresh |
Good to Fix | 2.2.4, 3.2.5 | None |
oobee-grading-text-contents |
Checks that text content is clear and plain and can be understood without effort | Manual Review Required | 3.1.5 | None |
Best-practice rules
Best-practice rules do not map to a WCAG criterion. All are Good to Fix.
| Rule ID | Description |
|---|---|
accesskeys |
Ensures every accesskey attribute value is unique |
aria-dialog-name |
Ensures every ARIA dialog and alertdialog node has an accessible name |
aria-text |
Ensures role="text" is used on elements with no focusable descendants |
aria-treeitem-name |
Ensures every ARIA treeitem node has an accessible name |
empty-heading |
Ensures headings have discernible text |
empty-table-header |
Ensures table headers have discernible text |
frame-tested |
Ensures <iframe> and <frame> elements contain the axe-core script |
heading-order |
Ensures the order of headings is semantically correct |
image-redundant-alt |
Ensures image alternative text is not repeated as text |
label-title-only |
Ensures every form element has a visible label and is not labelled only by hidden labels, title or aria-describedby |
landmark-banner-is-top-level |
Ensures the banner landmark is at top level |
landmark-complementary-is-top-level |
Ensures the complementary landmark or aside is at top level |
landmark-contentinfo-is-top-level |
Ensures the contentinfo landmark is at top level |
landmark-main-is-top-level |
Ensures the main landmark is at top level |
landmark-no-duplicate-banner |
Ensures the document has at most one banner landmark |
landmark-no-duplicate-contentinfo |
Ensures the document has at most one contentinfo landmark |
landmark-no-duplicate-main |
Ensures the document has at most one main landmark |
landmark-one-main |
Ensures the document has a main landmark |
landmark-unique |
Ensures landmarks have a unique role or role, label and title combination |
meta-viewport-large |
Ensures <meta name="viewport"> can scale a significant amount |
page-has-heading-one |
Ensures the page, or at least one of its frames, contains a level-one heading |
presentation-role-conflict |
Ensures elements marked as presentational have no global ARIA or tabindex, so all screen readers ignore them |
region |
Ensures all page content is contained by landmarks |
scope-attr-valid |
Ensures the scope attribute is used correctly on tables |
skip-link |
Ensures all skip links have a focusable target |
tabindex |
Ensures tabindex values are not greater than 0 |
table-duplicate-name |
Ensures the <caption> element does not contain the same text as the summary attribute |
Readability grading
The oobee-grading-text-contents rule grades how easy the page text is to read. It maps to WCAG 3.1.5 (Reading Level), runs only when AAA rules are enabled, and reports under Manual Review Required.
| Stage | Behaviour |
|---|---|
| Text extraction | Oobee takes the text of all <p> elements and keeps the segments that end with ., ! or ? as sentences |
| Minimum length | If the sentences total fewer than 20 words, Oobee skips grading and treats the page as a pass |
| Scoring | Oobee calculates a Flesch Reading Ease score with the text-readability library |
| Flagging | A score of 50 or below is flagged as potentially difficult to understand, and the message reports the score. A score above 50 passes |
| Flesch score | Interpretation |
|---|---|
| 90 to 100 | Very easy to read (5th grade) |
| 60 to 70 | Easily understood by 13 to 15 year olds |
| 50 or below | Difficult: college level or above |
| 0 to 30 | Very difficult: best understood by university graduates |