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
- How to validate
- The W3C Markup Validation Service
- In the editor
- In the build
- The Issues tab
- Errors worth understanding
- Duplicate ids
- Bad nesting
- Missing required attributes
- Obsolete elements and attributes
- Unclosed elements
- Stray end tags
- Warnings versus errors
- What the validator cannot tell you
- Validating generated pages
- Related checks worth running
- Important rules
- Common mistakes
- Best practices
- Practice
-
HTML Basics
- What is HTML: The Structure Layer of Every Web Page
- HTML Document Structure: DOCTYPE, html, head and body
- Elements, Tags and Attributes: The Vocabulary of HTML
- HTML Comments: Notes That Ship With Your Code
- Block Level and Inline Elements
- Writing and Running Your First HTML Page
- How a Browser Turns Markup Into a Page
- Text and Formatting
- Links and Navigation
- Images and Media
- Lists
- Tables
-
Forms
- Form Structure: form, action and method
- Input Types: Text, Email, Number, Date and the Rest
- Labels: The Most Important Element in a Form
- Checkboxes, Radio Buttons and Grouping
- select, option, optgroup and datalist
- textarea, File Uploads and Hidden Fields
- Buttons: submit, reset and button
- Built In Form Validation
- GET or POST: What Happens When a Form Is Submitted
- Semantic HTML
- HTML5 Features
- Head and Metadata
- HTML with CSS
- HTML with JavaScript
- Accessibility
-
HTML SEO
- How Google Works: Crawling, Indexing and Ranking
- SEO Friendly HTML Structure
- Titles and Descriptions That Earn Clicks
- Headings and Content Structure for Search
- Internal Linking and Anchor Text
- robots.txt and XML Sitemaps
- Canonical URLs and Duplicate Content
- Structured Data and JSON-LD
- Image SEO
- Core Web Vitals and Mobile Friendliness
- DevTools and Debugging
- Editor Productivity
- HTML Best Practices
- HTML Projects
- Advanced Projects
- Practice and Exams
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, cellspacingThey 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
| Level | Means |
|---|---|
| Error | The specification is violated. Fix it. |
| Warning | Legal but questionable, such as an empty heading. |
| Info | Advisory. |
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.
Related checks worth running
| Check | Finds |
|---|---|
| HTML validator | Specification violations |
| Link checker | Broken internal and external links |
| Accessibility scanner | Missing labels, contrast, ARIA problems |
| Lighthouse | Performance, SEO and best practice issues |
| Rich Results Test | Structured 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
- Validate a page you built and fix every error.
- Deliberately duplicate an id and read what the validator says.
- Remove a closing
</div>and note how far from the real mistake the reported line is. - Validate a generated page and compare the errors with those in its template.