HTML Validator
Check simple HTML fragments for mismatched or unclosed tags using a lightweight tag-stack validator.
Treat this page as a tag-stack exercise
The HTML Validator checks one structural property: whether tag-like strings close in last-opened, first-closed order. It extracts tags with a regular expression, pushes each opening tag name onto a stack, and pops the stack when a closing tag arrives. A closing name that differs from the stack top produces a mismatch message. Any names left at the end are reported as unclosed.
That is useful for locating a missing </p> in a simple fragment. It is not equivalent to the WHATWG HTML checker, the W3C Nu HTML Checker, a DOM parser, or an accessibility audit. The browser HTML parsing algorithm recognizes void elements, raw-text states, implied end tags, foreign content, and extensive error recovery. This page does not model those rules. Its success message means only that its extracted tags balanced according to its stack.
Read a failure from the inside out
The preloaded sample contains:
<div class="card">
<h2>Title</h2>
<p>Paragraph content
</div>
The opening names are pushed as div, then h2; h2 closes correctly; p is pushed. When </div> appears, p is still on top. The log reports:
Tag Mismatch: Found closing </div> without matching opening tag.
Adding </p> before </div> empties the stack and changes the message to HTML tag syntax structure is valid. Because validation reruns whenever the editor changes, there is no submit button. The Tag Linter Log always reflects the current string.
The three possible outcomes
A mismatched closing tag
If a closing tag has no opening tag at the current nesting point, the first mismatch stops the scan. The message names the closing tag encountered, not the opening tag expected. Repairing that issue may reveal another one later in the document.
Unclosed tags remaining
If no closing mismatch occurs but openings remain, the log lists the names retained by the stack:
Unclosed tags remaining: <main>, <section>, <p>
The list follows opening order. The most recently opened name is the one that normally needs attention first.
A balanced stack
When every recognized opening token is paired in stack order, the success message appears. This result does not establish standards conformance, legal element nesting, required attributes, a correct document outline, or accessibility.
What the extractor recognizes
The tag matcher looks for < or </, followed by letters or digits and then any non-> characters until >. Opening names are taken from the text before the first space. Closing names are taken from between </ and > and trimmed. Tags ending exactly in /> are not pushed.
These rules have direct consequences:
- Tag-name comparison is case-sensitive even though ordinary HTML tag names are ASCII case-insensitive.
- Hyphenated custom elements are not matched because the initial name pattern permits only letters and digits before the rest of the token.
- A
>inside a quoted attribute can end the regular-expression match prematurely. - Comments and doctypes are not treated as normal opening tags by the initial name requirement.
- Names inside script strings or escaped examples may be mistaken for actual markup.
- No source line or column is reported.
Void elements produce expected false alarms
HTML void elements do not have closing tags. Common examples include img, input, br, hr, meta, link, source, and area. In HTML syntax, this is normal:
<div>
<img src="cover.jpg" alt="Book cover">
</div>
The stack checker pushes img because the token does not end in />. It then sees </div> while img is on top and reports a mismatch. Writing <img ... /> avoids that particular warning in this tool, but the slash is not required by HTML. Do not modify valid project style solely to satisfy this simplified linter.
Similarly, HTML permits omitted end tags in defined contexts, such as some li, p, dt, dd, tr, th, td, and option situations. A standards parser applies those rules; this stack does not.
Problems that a balanced stack cannot find
Consider this source:
<html>
<head><title>Example</title></head>
<body>
<img src="hero.jpg" alt="">
<button><a href="/buy">Buy</a></button>
</body>
</html>
The void img causes this tool trouble unless written with />, while other important questions remain untouched. Is an empty alt appropriate for this image? Is interactive content nested legally? Is the language declared? Are landmark and heading structures suitable? Does the link name communicate its destination? Tag balancing cannot answer any of them.
The page also does not check duplicate IDs, attribute quoting, character references, obsolete features, required document metadata, ARIA roles and states, CSS, JavaScript, CSP, or URL validity. Those belong to other validators and tests.
A useful validation ladder
- Paste a small, ordinary fragment when you suspect a missing or out-of-order closing tag.
- Read the first mismatch or the remaining-stack list.
- Account for void elements and optional end-tag rules before changing valid HTML.
- Repair the source in the real file and rerun the project’s formatter.
- Submit the complete document to a WHATWG-aware online HTML validator or Nu Html Checker.
- Inspect the resulting DOM in browser developer tools, because error recovery can differ from source indentation.
- Run accessibility checks, keyboard testing, and assistive-technology review separately.
- Test templates after rendering, not only before dynamic values and conditionals are resolved.
This sequence puts the lightweight online HTML tag checker in its proper place: a fast clue near the beginning, not a release gate at the end.
Debugging server templates and components
Template sources often contain branches that individually look unbalanced but produce balanced HTML at runtime. Conversely, each source file may balance while the composed page fails because slots, partials, or conditions interact. The checker has no awareness of component boundaries or template expressions.
For React JSX, use the TypeScript or Babel parser configured by the project. For Astro, Vue, Svelte, Angular, Liquid, and server-side templates, use framework-aware diagnostics and validate rendered output. Custom elements with hyphens are especially unsuitable here because the extraction pattern does not capture their full name correctly.
Script and style blocks present another concern. Their contents can include strings such as "</div>" or comparisons with <. A real HTML tokenizer enters raw-text or script-data states. This linter searches the entire source uniformly, so code text can generate phantom tags. Remove or isolate such blocks when using the page to inspect surrounding structure, but preserve the original for real testing.
When the check is still handy
A compact stack linter earns its keep during pair debugging, educational demonstrations of nesting, and first-pass inspection of a small static fragment containing ordinary paired elements. It can quickly expose this pattern:
<section><div><p>Text</div></p></section>
The first illegal closure is apparent without waiting for a service or installing a package. Because the log responds instantly, you can add the suspected closing tag and observe the stack result.
It is less useful on complete modern documents rich in void tags, web components, embedded code, or framework expressions. In those cases, false positives can outnumber actionable findings.
Questions this checker can and cannot answer
| Question | Answered here? |
|---|---|
| Did recognized paired tags close in stack order? | Yes |
| Which source line contains the error? | No |
Is a void element legal without />? |
Not modeled |
| Is element nesting valid under HTML content models? | No |
| Will the browser repair this markup? | No |
| Does the page meet WCAG requirements? | No |
| Are custom-element names handled accurately? | No |
| Is rendered template output valid? | Only if separately pasted, with the same limitations |
FAQ from real markup reviews
Why does <img> appear unclosed?
The checker pushes any recognized opening token that does not end with />. It has no built-in void-element list, so normal HTML void syntax can trigger a false mismatch.
Are tag names case-insensitive?
Not in this implementation. Names are compared as strings. <DIV></div> can fail even though HTML syntax treats ordinary tag names case-insensitively.
Does it support web components?
Not reliably. The extractor’s tag-name portion is limited to letters and digits, so a hyphenated custom-element name is not modeled correctly.
Why is there no line number?
The tool works from a list of matched tag strings rather than retaining source positions. Its messages report names only.
Does the valid message mean the DOM is correct?
No. It means the simplified stack ended empty without encountering a mismatched closing token. Browser parsing and HTML content rules are much broader.
Can I copy or download a report?
No. The implemented interface has an editable markup area and a status log only.
Does it test accessibility?
No. Accessible names, keyboard behavior, semantics, contrast, ARIA, and WCAG success criteria require dedicated inspection and testing.
Should I self-close every tag to satisfy it?
No. Use HTML’s actual syntax rules and your project style. Self-closing normal non-void HTML elements does not make them self-closing under the HTML parsing algorithm.