Methodology & scope
Here we honestly explain what NormHarbor scans, how it works, and what's out of scope. Our goal is trust, not overpromising.
RulesWCAG rules we scan
| Rule | Title | What's checked |
|---|---|---|
| WCAG 1.1.1 (A) | Images without alternative text | Every <img> has an alt attribute (decorative images marked role="presentation"/aria-hidden are excluded). |
| WCAG 3.1.1 (A) | Page language (html lang) not set | The <html> tag has a valid lang attribute. |
| WCAG 2.4.2 (A) | Page title (<title>) missing or empty | The <title> tag is present and not empty. |
| WCAG 1.3.1 (A) | Form fields without a label | Every input/select/textarea is linked to a <label for>, aria-label, aria-labelledby, or an enclosing <label>. |
| WCAG 2.4.4 (A) | Links without text | Every <a href> has an accessible name: visible text, aria-label, or an inner image with alt. |
| WCAG 4.1.2 (A) | Buttons without an accessible name | Every <button> has an accessible name (text or aria-label). |
| WCAG 4.1.2 (A) | iframe without title | Every non-hidden <iframe> has a title attribute. |
| WCAG 1.4.4 (AA) | Zoom disabled | The viewport meta tag restricts scaling via user-scalable=no or maximum-scale<2. |
| WCAG 4.1.1 (A) | Duplicate id values | The same id value is used on more than one element on the page. |
| WCAG 2.4.3 (A) | Positive tabindex (focus order altered) | Presence of elements with a tabindex attribute greater than 0 (alters the DOM focus order). |
| WCAG 1.3.1 (A) | No h1 heading on the page | At least one <h1> is present on the page (when a heading hierarchy exists). |
| WCAG 1.3.1 (A) | Heading level skipped (e.g. h2→h4) | Heading levels (h1–h6) proceed in order, without skipped levels. |
| WCAG 1.2.2 (A) | Missing captions (track) for video/audio | A <track kind="captions"> element is present inside <video>/<audio>. |
| WCAG 1.4.3 (AA) | Insufficient color contrast | Text/background contrast ratio ≥ 4.5:1 (≥ 3:1 for large text). Partial detection: only inline styles (color + background-color); colors set via CSS classes require a manual audit. |
| WCAG 1.3.1 (A) | Invalid ARIA reference | aria-labelledby/aria-describedby point to an id that exists on the page. |
| WCAG 4.1.2 (A) | Hidden (aria-hidden) but focusable element | No focusable element (link, button, input, tabindex) is marked aria-hidden="true". |
| WCAG 1.3.1 (A) | Data table without headers (<th>) | Data tables (containing <td>) have at least one <th>; tables with role="presentation" are excluded. |
| WCAG 2.4.4 (A) | Generic/non-descriptive link text | Links don't use generic text such as "click here", "read more", "here" that doesn't describe the destination. |
| WCAG 1.4.2 (A) | Auto-playing media content | Audio/video doesn't autoplay without controls (audio) or without muted (video). |
Audit method
NormHarbor fetches the target URL server-side and statically analyzes the HTML source against the rules listed above. This returns a result in seconds, without opening a browser or running JavaScript.
Out of scope — what we intentionally don't measure
- Static analysis doesn't fully cover JavaScript-rendered content; a manual audit is recommended. Content/elements not present in the static HTML — added to the DOM only via client-side JS — are not scanned.
- Color contrast (1.4.3) — requires real rendering and computed CSS, which can't be measured from static HTML. (See our dedicated color contrast tool.)
- Keyboard traps and focus visibility (2.1.2 / 2.4.7) — require real interaction/a browser.
- Dynamic ARIA states (4.1.3) — states like aria-live, aria-expanded that change via JS require rendering.
An honest statement about scope
Automated audits don't replace manual testing. Industry data suggests automated tools catch roughly 30–40% of WCAG issues; the rest (context, meaning, real keyboard/screen-reader experience) needs human review.
Use NormHarbor for initial diagnosis and continuous regression monitoring; before issuing a legal compliance statement, always have a manual/expert audit done. This is not legal advice.
← Home · Tools · Scan vs. audit · Overlay vs. code fix · EU (EAA) guide