Why does broken HTML still display?
HTML parsers never stop with an error. The HTML Living Standard defines how a browser must recover from every kind of mistake, step by step, so Chrome, Firefox and Safari all repair a broken page the same way. That is why a page with a dozen errors can still look fine.
The cost is that bugs hide. The browser builds a DOM that differs from what you wrote, and the symptom shows up somewhere else: a CSS rule that does not match, a querySelector that returns null, a form field that is not sent, or a screen reader reading the footer in the middle of an article. Debugging HTML is mostly finding the gap between your source and the tree the browser built.
What do the most common errors look like?
Each of these looks harmless when you scan the code, which is why tools beat eyeballs.
<!-- Unclosed: the footer ends up inside .card -->
<div class="card">
<h2>Saturday ringing</h2>
<footer>…</footer>- Unclosed tags: a missing
</div>makes everything after it a child of that div, so your footer inherits the card's padding. - Overlapping tags:
<b><i>text</b></i>gets rebuilt by the parser, which closes and reopens elements to repair it. - Invalid nesting: a
<div>inside a<p>closes the paragraph early, leaving an empty<p></p>after the div. - Duplicate ids:
<label for>, fragment links andgetElementByIdonly find the first match. - Unquoted values with spaces:
class=card widesets class tocardand adds an empty attribute namedwide. - Unescaped characters: a
<in text such asif a<bcan start a tag. Write<. - Self-closing syntax on non-void elements:
<div />is treated as an open<div>, and everything after it ends up inside.


<footer> really ended up.How is view source different from the Elements panel?
View source (Ctrl+U, or Cmd+Option+U on a Mac) shows the exact text the server sent. The Elements panel in DevTools shows the live DOM: the tree after error recovery and after every script has run. When an element appears in a different place in Elements than in your source, the parser or a script moved it. Comparing the two is the fastest way to find a parsing bug.
In the Elements panel, right-click any node to edit it as HTML, add attributes, or break on changes. Press Ctrl+F (Cmd+F) inside the panel to search the DOM by text, by CSS selector, or by XPath. Searching #main shows whether the id exists and how many times.
The Styles pane next to it shows which CSS rules match the selected element and which are crossed out. If a rule you expect is missing completely, the selector does not match the element, which often means the DOM structure is not what you think it is.
How do I use the W3C validator well?
The Nu HTML Checker at validator.w3.org/nu reads your markup and lists errors and warnings with line numbers. Paste code, upload a file, or give it a public URL. For a page behind a login or on localhost, paste the source.
Fix the first error first and re-run. One unclosed element can produce twenty later messages that vanish once it is fixed. Treat errors as bugs. Read warnings, since some point to real problems, such as a section with no heading, and some are advice you can ignore.
Validation proves the syntax and nesting are correct. It does not prove the page is accessible or that alt text makes sense. A page can pass and still use a <div> as a button with an ARIA role bolted on. Use it as the first check, with the keyboard and accessibility checks after.
How do I debug a form that sends the wrong data?
Open the Network panel in DevTools, submit the form, and click the request. The Payload tab lists exactly which fields were sent and with what values. If a field is missing, it almost always has no name attribute, is disabled, or sits outside the <form> without a form attribute pointing back to it.
Check the button too. A <button> inside a form defaults to type="submit", so a "Show password" button without type="button" submits the form. In the Elements panel, select the form and type $0.elements in the Console to see every control the form owns.
If a label does not focus its field when clicked, the label's for value does not match an id, or the id is duplicated. The Accessibility pane will show that input with an empty name.
<form action="/join" method="post">
<label for="em">Email</label>
<input id="em" name="email" type="email"> <!-- no name = not sent -->
<button type="button" id="show">Show tips</button>
<button>Join the bird club</button>
</form>Which Console tricks speed up HTML debugging?
The Console in Chrome, Edge and Firefox has shortcuts aimed at inspecting the DOM. These help most when a script cannot find an element or a page behaves differently from the source.
document.querySelectorAll('[id]').forEach(el => {
if (document.querySelectorAll('#' + CSS.escape(el.id)).length > 1) console.log('Duplicate id:', el.id);
});$0is the element selected in the Elements panel.$1is the one before it.$('selector')and$$('selector')are short forms ofquerySelectorandquerySelectorAll.document.activeElementtells you what has focus right now.inspect(element)jumps from the Console to that node in the Elements panel.- A script that runs before the element exists gets
null. Check whether the script is in the head withoutdefer. - Red errors in the Console about failed resources (404 on a stylesheet or image) often explain a page that looks broken.
How do I check the accessibility tree?
Chrome and Edge show an Accessibility pane under Elements. Select a node and it shows the computed role, the accessible name and where that name came from. Firefox has an Accessibility panel that shows the whole tree and can flag contrast and keyboard issues. Chrome can also show the full accessibility tree in place of the DOM tree, using a toggle at the top of the Elements panel.
This is how you find a button whose name is empty because its only content is an SVG, or a heading that is really a styled <div>. Fix the HTML and the tree updates on the spot.
What should I check in AI-generated HTML?
Code assistants produce markup that renders, which is a low bar. Read it the way you would review a teammate's pull request. Run it through the validator first, then look for these patterns, which survive validation.
- Clickable
<div>and<span>elements that should be<button>or<a href>. - Repeated ids from copy-pasted cards, often
id="card"on every item. - Labels whose
forpoints to an id that was renamed elsewhere. - Wrapper soup: five nested divs where one element would do.
- Attributes from old HTML such as
align,bgcolor,borderon tables, or<center>and<font>, which are obsolete. - Self-closing slashes on
<div />or<span />copied from JSX, which the HTML parser does not honour. - Made-up attributes that look plausible, like
alton a<div>orplaceholderon a<select>.
Field notes
- Browsers never stop on broken HTML, so mistakes can hide behind a page that looks fine.
- Tags must close in the reverse order they opened.
- The W3C validator lists errors with line numbers so you can find them fast.
Easy to get wrong
A <p> cannot contain a <div>. The browser closes the paragraph early and leaves a stray empty <p>.
Elements must close in reverse order. Overlapping tags get rebuilt by the parser in ways you did not intend.
Without quotes, the space ends the value, so wide becomes a separate empty attribute.
Questions people ask
How do I check if my HTML is valid?
Run it through the W3C Nu HTML Checker at validator.w3.org/nu, or use a linter in your editor.
Why does my page look fine but fail validation?
Browsers silently repair errors. The page displays, but its DOM may differ from your source, which can break CSS, scripts, and accessibility.
What happens if I use the same id twice?
The page still loads, but labels, fragment links, and scripts will only find the first match, so the second element is effectively unreachable.
What is the difference between page source and the DOM?
Source is the raw text sent by the server. The DOM is the live tree the browser built from it after error recovery and script changes.