Skip to content

WCAG Remediation Coverage

This document maps every WCAG success criterion and axe-core rule we detect against what the remediation service actually fixes. It answers the question: after remediation, which violations will be gone, which will remain, and which were never checked?

Last updated: 2026-03-07 (updated to reflect 14 total new auto-fixes: 7 from prior session + 7 Tier 1 deterministic fixes)


How the Remediation Service Works

Two services apply fixes in sequence:

  1. html-remediator.ts β€” Runs before axe-core. Applies static regex fixes (lang, headings, landmarks, tables, skip link) and calls a vision AI model (Gemini, Claude, or GPT-4o) to generate descriptive alt text for images.

  2. axe-fixer.ts β€” Runs after an initial axe-core audit. Applies deterministic regex fixes for 20 known violation types, then re-runs axe-core (up to 3 iterations). Reverts any change that increases the violation count.

Neither service modifies the semantic content of the document β€” they can add missing structural markup and set safe default attribute values, but they cannot rewrite prose, determine the correct language for a passage, or know what an unlabeled button is supposed to do.


Part 1: Violations the Service CAN Fix

1A β€” Fully Fixed (reliable, correct output)

These violations are deterministically correctable. The fix is structurally sound and will pass re-audit.

ViolationWCAG SCLevelFix AppliedService
Missing lang on <html>3.1.1AAdds lang="en"Both
Missing <title> element2.4.2AInserts <title>Document</title> into <head>Both
Missing <main> landmark2.4.1AWraps body content in <main role="main">Both
Missing skip navigation link2.4.1AInserts <a href="#main-content" class="skip-link"> after <body>html-remediator
Missing viewport meta tag1.4.4AAInserts <meta name="viewport" content="width=device-width, initial-scale=1.0">axe-fixer
Skipped heading levels (h1 β†’ h3)1.3.1AARemaps heading levels to sequential orderBoth
Table with no <th>1.3.1APromotes first-row <td> cells to <th scope="col">html-remediator
<th> with missing or invalid scope1.3.1AAdds scope="col" in <thead>, scope="row" for first <th> in <tbody>; removes invalid scope valueshtml-remediator
Duplicate element id attributes4.1.1AAppends -2, -3 suffix to duplicate IDs and updates all aria-labelledby, aria-describedby, aria-controls, aria-owns, and for references to renamed IDsStatic validator
Invalid ARIA role attribute (e.g., role="dropdown")4.1.2ARemoves the invalid role attribute β€” element falls back to its implicit semantic roleStatic validator
Empty <h1>–<h6> element1.3.1ARemoves the empty heading elementStatic validator
Orphan <li> outside <ul> or <ol>1.3.1AWraps orphan <li> elements in <ul>Both
Non-<li> direct children of <ul> or <ol>1.3.1AWraps invalid children in <li> using DOM parsing; nested lists are preservedStatic validator
<dl> with invalid child elements1.3.1AWraps invalid direct children of <dl> in <dd> using DOM parsingStatic validator
Layout table (no <th>, cells contain only block elements)1.3.2AAdds role="presentation" to the table β€” suppresses screen reader table semantics. Does not convert layout to CSS.Static validator
Missing ARIA live region (forms or feedback elements present)4.1.3AAAdds aria-live="polite" role="status" aria-atomic="true" to feedback-pattern elements; if none are present, injects a visually-hidden announcer <div> after <body>Static validator
text-align: justify in styles1.4.8AAARemoves from all inline styles and <style> blocks document-wideStatic validator
user-select: none in styles1.4.8AAARemoves from all inline styles and <style> blocks document-wideStatic validator
<listitem> not in list1.3.1ASame as orphan <li> β€” wraps in <ul>axe-fixer
Content outside landmark regionsBest Practiceβ€”Wraps orphan body content in <section role="region" aria-label="Content">axe-fixer
Duplicate landmark regionsBest Practiceβ€”Adds unique aria-label attributes to duplicate <nav>, <aside>, <section>, <form> elementsaxe-fixer
Scrollable region not keyboard accessible2.1.1AAdds tabindex="0" to scrollable overflow containersaxe-fixer
SVG with role="img" and no label1.1.1AAdds aria-label="Mathematical expression"axe-fixer

1B β€” Partially Fixed (fix is applied, but quality is limited or context-dependent)

These violations receive an automated fix that will satisfy the rule validator, but the result is a generic placeholder that does not communicate real meaning. A human or AI review pass is needed to complete the fix.

ViolationWCAG SCLevelFix AppliedLimitation
<img> missing alt attribute1.1.1AAI path (html-remediator): Vision model generates a contextual description. Fallback (axe-fixer): Adds alt="Image"The AI path requires a configured API key and image accessibility; the fallback alt="Image" is still a 1.1.1 violation for meaningful content β€” it tells a screen reader nothing
Empty <a href> (no link text)2.4.4AAdds aria-label="Link"”Link” communicates nothing about the destination β€” must be revised by a human
Empty <button>4.1.2AAdds aria-label="Button"”Button” communicates nothing about the action
Unlabeled <input>1.3.1AAdds aria-label="Input field"”Input field” communicates nothing about what data to enter
Color contrast below 4.5:1 (AA)1.4.3AAForces color: #1a1a1a !important; background-color: #ffffff !important on the failing elementOverrides author styles β€” may break the visual design; ratio is corrected but design is not restored
Color contrast below 7:1 (AAA)1.4.6AAASame approach as AA contrast fixSame limitation
Image-only links2.4.4AAdds aria-label from the contained <img> alt textOnly works if the <img> has meaningful alt; if alt is also generic, the link label will be too
Non-SVG element with role="img" and no label1.1.1AAdds aria-label="Image"Generic β€” does not describe the image content; requires human review
<input type="submit/button"> with no accessible name4.1.2AAdds value="Submit"”Submit” may not match the actual button purpose
Form field labeled only by title attributeBest Practiceβ€”Copies title value to aria-labelNo content knowledge required β€” value is already present in title; fix quality matches the existing title text
<select> with no accessible name1.3.1AAdds aria-label="Select an option"Generic β€” does not describe what is being selected

Part 2: Violations Detected But NOT Fixed

These violations appear in the audit report and are presented to the user with guidance, but the conversion service makes no change to the HTML. They require human judgment, content knowledge, design decisions, or structural changes that cannot be made without understanding the document.

2A β€” Static Validator Detects, No Fix Applied

ViolationWCAG SCLevelWhy Not Fixed
Invalid lang attribute value (e.g., lang="english" instead of lang="en")3.1.1ACannot determine the correct BCP 47 code from context
Present-but-meaningless alt text (e.g., alt="image", alt="photo", alt="img_001.png")1.1.1ARewriting requires understanding what the image depicts β€” needs AI vision or human review
Generic or non-descriptive heading text (β€œSection 2”, β€œContinued”, β€œ1.”)2.4.6AARewriting heading text requires understanding the document’s content
Empty <th> (table header with no text)1.3.1ACannot supply the missing header label without knowing what column it represents
<th> missing scope in complex multi-span tables1.3.1APosition-based scope inference is unreliable for merged cells β€” requires human review
Block element nested inside inline / anchor-inside-anchor4.1.1ANo safe generic fix β€” restructuring may change document meaning
ARIA attribute incompatible with element role4.1.2AReported as a warning; stripping the attribute would be unsafe without knowing the intended widget pattern
Color-only information in text content1.4.1AContent rewrite required β€” cannot add semantic meaning (icon, label) without knowing the intent
Sensory-only instructions (β€œclick the red button on the right”)1.3.3AProse rewrite required
Image of text (image whose alt is full prose content)1.4.5AACannot convert a rasterized image to actual HTML text
Non-Latin script without lang annotation3.1.2AAScript is detected, but the correct BCP 47 code cannot be inferred without language-detection
Same visible label on elements of different types3.2.4AAMay be intentional β€” requires content review
Color contrast via CSS cascade / var() / inherit1.4.3AAExternal stylesheets and CSS variables cannot be resolved by static HTML analysis
color-contrast-enhanced (7:1 AAA) via cascade1.4.6AAASame as above β€” axe-core checks this at render time but no static fix is possible
Non-descriptive link purpose (same text, different destinations)2.4.9AAARequires content rewrite to differentiate links
Non-descriptive section headings2.4.10AAACannot insert headings without knowing where section boundaries belong
Unexpanded abbreviations3.1.4AAAExpansion text requires a domain-specific dictionary

2B β€” axe-core Detects, Not in Fix Registry

These violations appear in axe-core audit results. The fix engine (axe-fixer.ts) does not have a fix function for them.

axe Rule IDWCAG SCLevelWhy Not Fixed
area-alt1.1.1AImage map <area> elements need descriptive alt β€” requires content knowledge
input-image-alt1.1.1A<input type="image"> needs alt β€” requires content knowledge
object-alt1.1.1A<object> elements need fallback text β€” requires content knowledge
summary-name4.1.2A<summary> without discernible text
bypass2.4.1ASkip mechanism missing β€” partially addressed by html-remediator’s skip link, but if axe flags this after remediation the skip link target may be broken
aria-hidden-focus4.1.2AFocusable element inside aria-hidden="true" β€” removing aria-hidden may expose content that was intentionally hidden
aria-hidden-body4.1.2ACannot safely remove aria-hidden from <body>
nested-interactive4.1.2AStructural HTML issue β€” restructuring may break layout
form-field-multiple-labels1.3.1AMultiple <label> elements for one input β€” requires knowing which label is correct
td-headers-attr1.3.1Aheaders attribute references non-existent IDs β€” requires table restructuring
th-has-data-cells1.3.1ATable header with no associated data cells β€” structural table issue
frame-title4.1.2A<iframe> without an accessible name β€” requires knowing what the frame contains
frame-title-unique4.1.2ADuplicate frame titles β€” requires knowing each frame’s purpose
no-autoplay-audio1.4.2AAudio autoplay β€” removing the autoplay attribute may break intended behavior
video-caption1.2.2AVideo without captions β€” caption generation requires a transcription service
non-text-contrast1.4.11AAUI component and focus indicator contrast β€” CSS-dependent, cannot override safely
focus-visible2.4.7AAFocus indicator not visible β€” CSS-dependent
target-size2.5.8AATouch target too small β€” requires CSS layout changes
autocomplete-valid1.3.5AAInvalid autocomplete attribute value β€” removing it may be correct but context-dependent
avoid-inline-spacing1.4.12AAInline CSS locks text spacing β€” removing specific inline properties requires knowing which properties to target
valid-lang3.1.2AAInvalid lang attribute on element β€” correct code cannot be inferred
color-contrast (via CSS cascade)1.4.3AAColor contrast failures caused by external stylesheets, CSS variables, or inherit β€” cannot be resolved by regex on HTML alone
identical-links-same-purpose2.4.9AAASame visible text, different href β€” requires content understanding to resolve
blink / marquee2.2.2AElements exist but removing them changes document content
aria-* rules (braille, deprecated roles, conditional attrs, prohibited attrs, required children/parent, etc.)4.1.2AComplex ARIA structural requirements β€” cannot correct without knowing the intended widget pattern
Various landmark best-practice rules (landmark-banner-is-top-level, landmark-contentinfo-is-top-level, etc.)Best Practiceβ€”Require document restructuring
page-has-heading-oneBest Practiceβ€”Cannot add an <h1> without knowing what the document title should be
image-redundant-altBest Practiceβ€”Alt text duplicates surrounding visible text β€” requires content review
presentation-role-conflictBest Practiceβ€”Element has conflicting semantic role β€” requires structural review
table-duplicate-nameBest Practiceβ€”<caption> and summary are identical β€” requires content review

2C β€” Browser Checks Detect, No Fix Applied

These checks run in Puppeteer and produce detailed diagnostic results, but no HTML transformation is performed. The underlying cause (fixed-width CSS, fixed-height containers, positive tabindex values) requires manual CSS or HTML changes.

CheckWCAG SCLevelWhat Is DetectedWhy Not Fixed
checkResizeText() β€” horizontal overflow at 200% zoom1.4.4AAElements where scrollWidth > innerWidth and overflow:hidden elements where content is clipped at zoomFixed-width tables and absolute layouts from PDF reconstruction require CSS rewrite β€” no safe generic transform
checkResizeText() β€” content clipping at 200% zoom1.4.4AASpecific elements with overflow: hidden that clip content at 200%Same as above
checkTextSpacing() β€” content clipping after WCAG spacing overrides1.4.12AAElements with overflow: hidden where scrollHeight increases past clientHeight after forced spacingFixed-height containers need their height removed or changed to min-height β€” unsafe to automate
checkFocusOrder() β€” tab sequence disrupted by positive tabindex2.4.3AElements whose tab position differs from DOM position by more than 2Removing positive tabindex values may break intentional keyboard navigation patterns; tabindex on each flagged element must be reviewed individually
checkFocusOrder() β€” interactive element removed from tab sequence2.4.3Atabindex="-1" on elements with no alternative keyboard pathCannot determine whether the removal was intentional

Part 3: Not Checked β€” Cannot Be Tested

These WCAG success criteria are not evaluated by any layer of the pipeline. No violation is detected, no report entry is generated, and no fix is applied. They require live media playback, real keyboard/pointer interaction, form submission, or device capabilities that are absent from a static document conversion pipeline. Users whose documents may involve these criteria must perform manual verification.

Not Checked (require live interaction or media)

WCAG SCLevelReason
1.2.1 Audio-only / Video-onlyARequires media playback
1.2.2 Captions (Prerecorded)ARequires reading caption tracks
1.2.3 Audio Description or Media AlternativeARequires media playback
1.2.4 Captions (Live)AARequires live stream
1.2.5 Audio Description (Prerecorded)AARequires media playback
1.4.13 Content on Hover or FocusAARequires triggering hover/focus states
2.1.2 No Keyboard TrapARequires live keyboard navigation
2.3.1 Three FlashesARequires frame-by-frame animation measurement
3.2.1 On FocusARequires triggering focus events
3.2.2 On InputARequires triggering input events
3.3.1 Error IdentificationARequires form submission with invalid data
3.3.3 Error SuggestionAARequires form submission
3.3.4 Error PreventionAARequires form submission

Not Applicable to This Product

WCAG SCLevelReason
1.3.4 OrientationAAConverted documents do not lock orientation
1.3.5 Identify Input PurposeAAautocomplete is for account forms, not converted document tables
2.1.4 Character Key ShortcutsAANo single-character shortcuts in converted output
2.2.1 Timing AdjustableANo time limits in static documents
2.2.2 Pause, Stop, HideANo auto-updating or animated content
2.2.6 TimeoutsAAANo session timeouts
2.4.5 Multiple WaysAASingle document β€” no site-level navigation
2.5.1 Pointer GesturesANo multi-touch gestures in static output
2.5.2 Pointer CancellationANo interaction flows
2.5.4 Motion ActuationAStatic document
3.2.3 Consistent NavigationAANo multi-page navigation
3.2.5 Change on RequestAAANo dynamic context changes
3.3.5 HelpAAAContext-sensitive help is a web-app concept
3.3.6 Error Prevention (All)AAANo user data submission

Summary

What Gets Fixed Automatically

CategoryCountNotes
Fully fixed (reliable, correct output)27 violationsDocument structure, landmarks, heading levels, table headers, list structure (orphan + non-li children), definition list, layout tables, live regions, visual presentation, duplicate IDs, invalid ARIA roles
Partially fixed (generic placeholder)11 violationsEmpty interactive elements get generic labels; images get AI-generated alt or alt="Image" fallback; inline contrast forced to best black/white choice; non-SVG role="img", submit buttons, title-only labels, unlabeled selects

What Remains After Remediation (Detected, Not Fixed)

These violations appear in the report. The user must resolve them.

CategoryCountNotes
Static checks β€” detected, no fix17 violationsRequire content knowledge: lang codes, meaningful alt text, heading content, complex table structure, ARIA intent, color-only prose, sensory instructions
axe-core rules β€” not in fix registry30+ rulesMedia content, complex ARIA, CSS-dependent contrast, iframe titles, form structure
Browser checks β€” detected only3 checks (5 failure types)Fixed-width overflow, text spacing clipping, tab order disruption β€” require CSS or markup restructuring

What Cannot Be Tested (Not Checked By Any Layer)

No report entry is produced for these. Manual verification is required.

CategoryCountNotes
Require live media or interaction13 criteriaMedia captions/descriptions, keyboard traps, flash threshold, form submission events, hover/focus popups
Not applicable to static document output14 criteriaOrientation lock, timing, multi-page navigation, pointer gestures, session timeouts

The Most Common Remaining Violations in PDF-to-HTML Output

These are the violations most likely to appear in the final report that the service cannot automatically resolve:

ViolationFrequencyFix Required
image-alt-meaningful β€” AI alt is present-but-genericHighHuman review of every generated alt text
link-name β€” empty links get aria-label="Link"MediumAdd descriptive purpose to each empty link
button-name β€” empty buttons get aria-label="Button"MediumAdd descriptive action to each empty button
heading-descriptive β€” headings contain only numbers or β€œSection N”HighRewrite heading text with meaningful labels
th-has-scope / td-headers-attr in complex tablesMediumManual scope and headers attribute review
color-contrast via CSS cascadeMediumFix CSS stylesheet; inline auto-fix is best-effort only
1.4.4 Resize Text β€” fixed-width tables overflow at zoomHighReplace pixel widths with max-width: 100% or percentages
1.4.12 Text Spacing β€” fixed-height containers clipMediumReplace height: Npx with min-height: Npx
non-text-contrast β€” UI component colorsLowCSS changes to borders, icons, focus indicators
lang-of-parts β€” embedded non-Latin scriptMediumAdd lang attribute to affected spans; requires language detection