HTML is lenient, and that hides mistakes
Browsers almost never refuse HTML. A stray </span> is ignored, a missing > swallows the next tag into an attribute, and the page renders anyway, just not the way you intended. That is why structural errors in email templates, CMS snippets and server-rendered fragments go unnoticed until a layout breaks.
This page parses your markup with the same HTML parser Prettier uses and reports what a careful reader would flag:
- A closing tag with nothing to close, such as
</span>when the open element is a<p>, or a</div>after</html>. Usually an element was closed too early or a tag name was mistyped. - An opening tag that is never terminated, as in
<button class="cta"<span>, where a missing>merges two tags. - End tags on void elements:
<img>,<br>,<input>and<meta>cannot have a closing tag, so</img>is an error. - Unclosed attribute quotes or comments, reported as an unexpected end of input at the point where the parser ran out of text.
What is deliberately allowed
HTML has optional end tags, and the checker follows the spec rather than XHTML habits. <li>, <p>, <td>, <tr> and <option> close automatically when the next sibling starts, so <ul><li>One<li>Two</ul> is valid. Custom elements such as <order-summary> and boolean attributes without values are fine. Uppercase tag names are fine too. If you paste a fragment rather than a full document, it is validated as a fragment; no <!DOCTYPE> or <html> wrapper is required.
Reading the report
The line and column of the first problem are highlighted in the input, and the message comes from the parser, for example Unexpected closing tag "span" followed by a note about implied end tags. Count backwards from the reported position to find the element that was closed early. Until the markup parses again, the formatted HTML from your last good edit stays visible, faded, in the output pane. Once it parses, switch to the Preview tab to see the rendered result, which is sanitised before display.
Keyboard users can format with Ctrl/Cmd+Enter and copy the result with Ctrl/Cmd+Shift+C. All parsing is local to your browser.
Not a W3C conformance checker
Structural parsing is only part of HTML validity. This tool does not check content models (a <button> nested inside another <button>, a <li> outside a list), duplicate id values, duplicate attributes, missing alt text, deprecated elements or ARIA rules. An <a> that is never closed is also accepted, because the parser closes it at the end of its parent. For full conformance, run the page through the W3C Nu HTML Checker; for accessibility, use an audit tool such as axe or Lighthouse.
Examples
Closing the wrong element
Invalid: </span> closes nothing, because the open element is <strong>; the error points at the stray tag.
<section class="orders">
<h2>Orders</h2>
<p>3 orders are <strong>pending</span></p>
</section>Line 3, column 34: Unexpected closing tag "span". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tagsMissing > merges two tags
Invalid: the opening <button> tag is never terminated, so the parser cannot tell where its attributes end.
<button class="cta" onclick="checkout()"<span>Buy now</span></button>Line 1, column 1: Opening tag "button" not terminated.Closing tag on a void element
Invalid: <img> is a void element and cannot have an end tag.
<figure>
<img src="/img/keyboard.jpg" alt="Mechanical keyboard"></img>
<figcaption>KB-104</figcaption>
</figure>Line 2, column 58: Void elements do not have end tags "img"Optional end tags are valid
Passes: <td>, <tr> and <p> close themselves when the next one starts, exactly as the HTML spec allows.
<table>
<tr><td>KB-104<td>Keyboard<td>129.90
<tr><td>MS-220<td>Mouse<td>39.50
</table>
<p>Prices include GST
<p>Free delivery over 100 SGD<table>
<tr>
<td>KB-104</td>
<td>Keyboard</td>
<td>
129.90
<tr>
<td>MS-220</td>
<td>Mouse</td>
<td>39.50</td>
</tr>
</td>
</tr>
</table>
<p>Prices include GST</p>
<p>Free delivery over 100 SGD</p>
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Unexpected closing tag "span". It may happen when the tag has already been closed by another tag.Explained | An end tag does not match the element that is currently open, often after a typo or a copy that cut off part of a fragment. | Find the matching opening tag and correct the name, or delete the stray end tag. |
Opening tag "button" not terminated. | A tag is missing its closing >, usually right before another tag starts. | Add > after the last attribute. |
Void elements do not have end tags "img" | A closing tag was written for img, br, input, meta, link or another void element. | Delete the end tag; void elements stand alone, optionally written as <img … />. |
Unexpected character "EOF" | The input ended inside an attribute value or comment, typically a missing closing quote or -->. | Close the attribute quote or the comment near the reported position. |
Frequently asked questions
Does this replace the W3C HTML validator?
No. It checks that the markup parses into a sensible tree: matching tags, terminated tags and attributes. The W3C Nu checker also enforces content models, attribute rules and deprecated features.
Why is a missing </p> or </li> not an error?
Because HTML defines those end tags as optional. The parser closes the element automatically when a sibling starts or the parent ends.
Can I validate Vue or Angular templates here?
Use the dedicated Vue and Angular formatters instead. Their template syntax, such as @click or @if blocks, is parsed correctly there.
Does it check inline CSS and JavaScript?
Embedded <style> and <script> content is formatted along with the markup. To check either one on its own, paste it into the CSS or JavaScript validator.