Skip to main content

Markup is valid and well-formed

ab-000126 · accessibility-wcag.understandable.valid-markup
Severity: lowactive

Why it matters

Invalid HTML — duplicate IDs, improperly nested elements, unclosed tags — causes screen readers to parse the DOM incorrectly or skip content entirely. WCAG 2.2 SC 4.1.1 (Parsing) is a Level A requirement. Duplicate id values break aria-labelledby, aria-describedby, and for associations — the very attributes that connect form labels to inputs and error messages to fields. A heading nested inside a <button> confuses the accessibility tree in ways that vary unpredictably across screen readers.

Severity rationale

Low because markup errors produce inconsistent rather than universal failures — different browsers and AT combinations are affected differently — but duplicate IDs break ARIA relationships globally throughout the page, violating WCAG 2.2 SC 4.1.1 at Level A.

Remediation

Run automated HTML validation as part of your CI pipeline to catch duplicate IDs and nesting errors before they reach production.

# Install htmlhint as a dev dependency
npm install --save-dev htmlhint

# Add to package.json scripts
"lint:html": "htmlhint 'src/**/*.html' 'public/**/*.html'"

# Or use Nu Validator for rendered output in CI
npx @nicolo-ribaudo/nuhtml-check http://localhost:3000

For React/JSX specifically, duplicate id values are the most common violation. Search the codebase for hardcoded id= strings that appear more than once — every duplicate breaks any ARIA attribute referencing that ID. Also check for <div> or <p> inside <button> and <p> inside <p>, which are invalid nesting patterns that corrupt the accessibility tree.

Detection

  • ID: accessibility-wcag.understandable.valid-markup

  • Severity: low

  • What to look for: Enumerate every relevant item. Check for common HTML validity issues: duplicate IDs, improper nesting (e.g., <p> inside <p>, <div> inside <button>), missing closing tags, malformed attributes.

  • Pass criteria: At least 1 of the following conditions is met. Markup is valid per HTML5 spec. No duplicate IDs. Elements properly nested. All tags closed.

  • Fail criteria: Markup has duplicate IDs, improper nesting, or unclosed tags.

  • Skip (N/A) when: Never — valid markup applies to all HTML documents.

  • Detail on fail: Example: "Multiple elements with id='nav-menu'. Button contains a div. Unclosed span tags"

  • Remediation: Validate HTML with W3C Nu Validator or build-time tools:

    # Install in CI
    npm install --save-dev htmlhint
    
    # Run validation
    htmlhint "src/**/*.html"
    

    Or use VS Code extension: "HTML Hint" to check in real-time.

External references

Taxons

History