Validating HTML

The validator catches nesting errors, duplicate ids and missing attributes in seconds. A page that renders is not the same as a page that is correct.

Concept

HTML has no fatal syntax errors. The parser repairs anything broken and renders the page regardless, which means it looks right proves nothing about whether the markup is right.

A validator checks markup against the specification and reports every deviation. It takes seconds and catches a category of bug that is otherwise invisible until it breaks in another browser.

How to validate

The W3C Markup Validation Service

Three ways in: paste a URL, upload a file, or paste markup directly. The URL option is the most useful once a site is live, because it validates exactly what the server sends.

In the editor

Editor extensions validate as you type and mark problems in the gutter, which catches most errors before they reach a browser.

In the build

# a validator run over built output, failing the build on errors
npx html-validate "dist/**/*.html"

Adding this to continuous integration is what stops a fixed page from slowly decaying again.

The Issues tab

Browsers surface a subset of validity problems - duplicate ids, bad ARIA references, deprecated attributes - in the DevTools Issues tab, without any external tool.

Errors worth understanding

Duplicate ids

<input id="email">
<input id="email">   <!-- the label binds to the first one only -->

Not cosmetic. It breaks label association, fragment links, ARIA references and getElementById.

Bad nesting

<p><div>...</div></p>              <!-- a p cannot contain a div -->
<ul><div><li>...</li></div></ul>    <!-- only li may be a child of ul -->
<a><button>...</button></a>          <!-- interactive inside interactive -->
<strong><em>x</strong></em>          <!-- overlapping, not nested -->

Each is repaired differently by different browsers, which is exactly the class of bug that appears on one machine and not another.

Missing required attributes

<img src="a.jpg">                     <!-- alt is required -->
<html>                                <!-- lang should be present -->
<iframe src="..."></iframe>           <!-- title is needed -->

Obsolete elements and attributes

<center>, <font>, <big>, <marquee>
align, bgcolor, border, cellpadding, cellspacing

They still render, and they are invalid. Every one has a CSS equivalent.

Unclosed elements

<div class="card">
  <h3>Title</h3>
<!-- the div never closes, so everything after it nests inside -->

Usually reported as a mismatched end tag much further down the file, which is why the error line is often nowhere near the actual mistake.

Stray end tags

An extra </div> is discarded silently by the browser and reported clearly by the validator.

Warnings versus errors

LevelMeans
ErrorThe specification is violated. Fix it.
WarningLegal but questionable, such as an empty heading.
InfoAdvisory.

Aim for zero errors. Read every warning and decide deliberately rather than ignoring the list.

What the validator cannot tell you

  • Whether alt text is useful.
  • Whether headings are in a logical order - only that no level was skipped.
  • Whether link text makes sense out of context.
  • Whether the right element was chosen for the content.
  • Whether the page is usable by keyboard.
  • Whether the content is any good.

Validity is a floor, not a ceiling. A perfectly valid page can still be built entirely from divs.

Validating generated pages

Most real pages are assembled by a server or a framework, so validate the output, not the template. Common problems that only appear in output:

  • A component rendered in a loop producing duplicate ids.
  • A template inserting a block element inside a paragraph.
  • A partial that opens a tag another partial closes, valid in neither file alone.
  • User submitted content containing unescaped markup.
CheckFinds
HTML validatorSpecification violations
Link checkerBroken internal and external links
Accessibility scannerMissing labels, contrast, ARIA problems
LighthousePerformance, SEO and best practice issues
Rich Results TestStructured data problems

Important rules

  • A rendering page is not a valid page.
  • Ids must be unique.
  • Nesting rules are enforced by the parser whether you follow them or not.
  • Obsolete elements still render and are still invalid.
  • Validate the served output, not the source template.
  • Validity does not imply accessibility or quality.

Common mistakes

  • Never validating at all.
  • Validating once at launch and never again.
  • Ignoring duplicate id errors as cosmetic.
  • Validating a template rather than the rendered page.
  • Assuming a passing validator means an accessible page.
  • Chasing an error at the reported line when the real mistake is an unclosed tag far above it.

Best practices

  • Install an editor extension that validates as you type.
  • Validate every page template before release.
  • Add a validation step to continuous integration.
  • Fix errors, review warnings.
  • Check the DevTools Issues tab as a free second pass.
  • Pair validation with an accessibility scan and a link check.

Practice

  1. Validate a page you built and fix every error.
  2. Deliberately duplicate an id and read what the validator says.
  3. Remove a closing </div> and note how far from the real mistake the reported line is.
  4. Validate a generated page and compare the errors with those in its template.

Useful resources

Hand picked references for this topic
Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All HTML notes →
HTML

The Elements Panel

The Elements panel shows the live DOM, not your file. That difference is why it is the first place to look when markup behaves in a way the source doe...

Read more
HTML

Project Exams

Five larger assessments where the deliverable is a working site. Requirements, constraints and a rubric for each.

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.