HTML Guides for stray
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The <!DOCTYPE> declaration tells the browser which version and type of HTML the document uses. In HTML5, this is simply <!DOCTYPE html>. According to the HTML specification, the DOCTYPE must be the first thing in the document — before any elements, comments, or whitespace. There can also be only one DOCTYPE per document.
The W3C validator reports “Stray doctype” when it encounters a <!DOCTYPE> declaration in an unexpected location. This typically happens when:
- The DOCTYPE is accidentally duplicated somewhere in the document (e.g., inside the <head> or <body>).
- Multiple HTML documents have been inadvertently concatenated or pasted together.
- A template engine or build tool is injecting an extra DOCTYPE.
- The DOCTYPE was mistakenly placed after other content, such as a comment, whitespace from a BOM (byte order mark), or a stray character before it.
This matters because a misplaced DOCTYPE can force the browser into quirks mode, which causes it to emulate legacy rendering behavior. In quirks mode, CSS box model calculations, font sizing, and many other layout behaviors differ from standards mode, leading to unpredictable and inconsistent rendering across browsers. A stray DOCTYPE inside the document body is simply ignored, but it signals a structural problem that can also cause accessibility tools and parsers to behave unexpectedly.
To fix the issue:
- Search your document for all occurrences of <!DOCTYPE and remove any duplicates.
- Make sure the single remaining <!DOCTYPE html> is the absolute first thing in the file — no whitespace, no comments, no BOM characters before it.
- If you’re using templates or server-side includes, check that only one template is responsible for outputting the DOCTYPE.
Examples
❌ Incorrect: DOCTYPE duplicated inside the body
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<!DOCTYPE html>
<p>Hello, world!</p>
</body>
</html>
The second <!DOCTYPE html> inside the <body> is a stray doctype and will trigger the error.
❌ Incorrect: DOCTYPE appears after other content
<!-- This is my page -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Even a comment before the DOCTYPE can cause issues. The DOCTYPE must come first.
❌ Incorrect: Two documents concatenated together
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page One</title>
</head>
<body>
<p>First page content.</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page Two</title>
</head>
<body>
<p>Second page content.</p>
</body>
</html>
This often happens when templates are incorrectly assembled. The second DOCTYPE (and entire second document structure) is stray content.
✅ Correct: Single DOCTYPE at the very start
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
The <!DOCTYPE html> declaration appears exactly once, as the very first thing in the file, followed by the <html> element. This ensures the browser uses standards mode and the document is valid.
The HTML parser processes tags sequentially, maintaining a stack of open elements. When it encounters an end tag like </div>, it looks for a matching open <div> in the current scope. If no matching open element exists, the end tag is “stray” — it has nowhere to go and violates the HTML specification. Browsers will silently ignore stray end tags in most cases, but their presence signals structural problems in your markup that can lead to unpredictable rendering and layout issues.
This error matters for several reasons. First, stray end tags often indicate a deeper structural problem — if you have an extra </div>, your layout nesting may be wrong even if the browser renders it acceptably today. Second, assistive technologies like screen readers rely on correct document structure to convey meaning, and malformed HTML can confuse them. Third, clean, valid markup is easier to maintain and debug, especially in collaborative projects.
There are several common causes of this error:
Duplicate closing tags — The most frequent cause. You accidentally close the same element twice, so the second closing tag is stray.
Copy-paste remnants — When moving or deleting blocks of HTML, a closing tag gets left behind without its corresponding opening tag.
Mismatched nesting — Elements are improperly nested, causing the parser to close tags in an unexpected order and leaving orphaned end tags.
Closing void elements — Void elements like <br>, <img>, <hr>, and <input> never have closing tags. Writing </br> or </img> will produce this error.
To fix the issue, search your document for the stray end tag mentioned in the error, then either remove it if it’s a duplicate or add/move the corresponding opening tag if one is missing.
Examples
Duplicate closing tag
This is the most common scenario — an element is closed twice:
<!-- ❌ Bad: duplicate </ul> -->
<ul>
<li>Item one</li>
<li>Item two</li>
</ul>
</ul>
Remove the extra closing tag:
<!-- ✅ Good -->
<ul>
<li>Item one</li>
<li>Item two</li>
</ul>
Copy-paste leftover
After editing, a closing tag remains without its opening counterpart:
<!-- ❌ Bad: stray </p> with no matching <p> -->
<div>
<h2>Title</h2>
</p>
<span>Some text</span>
</div>
Remove the orphaned </p>:
<!-- ✅ Good -->
<div>
<h2>Title</h2>
<span>Some text</span>
</div>
Mismatched nesting
Incorrectly nested elements can produce stray end tags:
<!-- ❌ Bad: </section> closes before </div>, leaving </div> stray -->
<section>
<div>
<p>Content here</p>
</section>
</div>
Fix the nesting so inner elements close before outer ones:
<!-- ✅ Good -->
<section>
<div>
<p>Content here</p>
</div>
</section>
Closing a void element
Void elements have no closing tag. Adding one produces a stray end tag error:
<!-- ❌ Bad: <br> and <img> are void elements -->
<p>Line one<br></br>Line two</p>
<img src="photo.jpg" alt="A photo"></img>
Remove the closing tags for void elements:
<!-- ✅ Good -->
<p>Line one<br>Line two</p>
<img src="photo.jpg" alt="A photo">
Multiple stray tags from a removed wrapper
When you remove a wrapper element’s opening tag but forget the closing tag:
<!-- ❌ Bad: <main> was removed but </main> remains -->
<body>
<h1>Welcome</h1>
<p>Hello world</p>
</main>
</body>
Either remove the stray </main> or restore the opening tag:
<!-- ✅ Good: stray tag removed -->
<body>
<h1>Welcome</h1>
<p>Hello world</p>
</body>
<!-- ✅ Also good: wrapper restored -->
<body>
<main>
<h1>Welcome</h1>
<p>Hello world</p>
</main>
</body>
When dealing with deeply nested HTML, using consistent indentation and an editor with bracket/tag matching makes it much easier to spot these issues before they reach validation. Many code editors also highlight unmatched tags in real time.
A stray <br> happens when the <br> element, which is phrasing content, is placed in contexts that only allow specific children. Common mistakes include putting <br> directly inside <ul>, <ol>, <table>, <tr>, or outside <body>, and inserting it between block-level siblings to add spacing instead of using CSS. The validator flags this because it violates the HTML content model.
This matters for standards compliance, predictable rendering, and accessibility. Screen readers and assistive tech rely on correct structure (lists made of li, tables built from tr/td, sections within body). Misplaced <br> can produce confusing reading orders and inconsistent layout across browsers.
How to fix:
- Keep <br> only where phrasing content is allowed (typically inside text-flowing elements like p, span, li, td, caption).
- For spacing between blocks, use CSS margins instead of <br>.
- For lists, use proper li items; for tables, place text inside td/th; for forms, use grouping and CSS.
- Ensure no <br> appears outside <body> or inside elements that have restricted content models (ul, ol, table, tr, thead, tbody, tfoot, colgroup, select, dl directly, etc.).
- If a line break is purely presentational across viewports, consider CSS (display:block, white-space) instead of <br>.
Examples
Valid use inside phrasing content
<p>
First line.<br>
Second line.
</p>
Invalid: <br> directly inside a list (triggers the error)
<ul>
<br>
<li>Item 1</li>
<li>Item 2</li>
</ul>
Fix: remove the stray <br>; use list items only
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
Invalid: <br> outside <body> (triggers the error)
<!DOCTYPE html>
<html lang="en">
<head>
<title>Stray br Tag Example</title>
</head>
<br>
<body>
Content here.
</body>
</html>
Fix: move <br> inside the body (or use CSS if only spacing is needed)
<!DOCTYPE html>
<html lang="en">
<head>
<title>No Stray br Tag</title>
</head>
<body>
Content here.<br>
New line in body.
</body>
</html>
Invalid: <br> as a child of <table> (triggers the error)
<table>
<br>
<tr>
<td>A</td>
<td>B</td>
</tr>
</table>
Fix: use proper table rows and cells; place text inside cells
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>More A</td>
<td>More B</td>
</tr>
</table>
Invalid: using <br> for spacing between blocks (not allowed between siblings)
<div>Section A</div>
<br>
<div>Section B</div>
Fix: use CSS margins for spacing
<!DOCTYPE html>
<html lang="en">
<head>
<title>Spacing with CSS</title>
<style>
.block { margin-bottom: 1rem; }
</style>
</head>
<body>
<div class="block">Section A</div>
<div>Section B</div>
</body>
</html>
Valid alternatives where a break is needed in phrasing context
<li>
Address: 123 Main St.<br>
Suite 400
</li>
Tips:
- Use exactly <br> (no closing tag needed) and do not self-close as XML (<br />) unless your tooling requires it; both parse in HTML, but stick to HTML style for consistency.
- If you see multiple “stray start tag ‘br’” errors, check parent containers: fixing the first invalid parent often resolves many subsequent errors.
The HTML parser follows strict rules about where elements can appear. When it encounters a <div> in an unexpected location, it reports it as a “stray” start tag. The parser may attempt error recovery — often by ignoring the tag or moving it — but the resulting DOM tree may not match your intentions, leading to broken layouts or missing content.
There are several common causes of this error:
Placement after </body> or </html>: All visible content must live inside the <body> element. Any <div> appearing after </body> or </html> is stray because the document structure has already been closed.
Inside elements with restricted content models: Elements like <table>, <ul>, <ol>, and <select> only permit specific child elements. A <div> placed directly inside a <table> (outside of <thead>, <tbody>, <tfoot>, <tr>, <td>, or <th>) or directly inside a <ul> (which only allows <li> children) will trigger this error.
Missing closing tags: If you forget to close an element like </td>, </li>, or </p>, the parser may implicitly close it at a point that leaves your <div> orphaned in an invalid context. This is one of the trickiest causes because the <div> itself looks fine — the real problem is elsewhere.
Why this matters: Beyond standards compliance, a stray element can cause browsers to construct an unexpected DOM. This may break CSS layouts, cause JavaScript selectors to fail, and create accessibility issues where assistive technologies misinterpret the page structure.
Examples
Stray <div> after the closing </html> tag
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<p>Main content</p>
</body>
</html>
<div>
Some extra content
</div>
The <div> appears after the document has been fully closed. Move it inside <body>:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<p>Main content</p>
<div>
Some extra content
</div>
</body>
</html>
Stray <div> inside a <table>
<table>
<div class="wrapper">
<tr>
<td>Data</td>
</tr>
</div>
</table>
A <table> does not allow <div> as a direct child. Remove the <div> or restructure:
<div class="wrapper">
<table>
<tr>
<td>Data</td>
</tr>
</table>
</div>
Stray <div> inside a <ul>
<ul>
<div class="group">
<li>Item 1</li>
<li>Item 2</li>
</div>
</ul>
A <ul> only accepts <li> elements as direct children. Place the <div> inside each <li>, or wrap the entire list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
Stray <div> caused by a missing closing tag
<table>
<tr>
<td>Cell content
</tr>
</table>
<div>More content</div>
The missing </td> can cause parser confusion that makes the <div> appear stray in some contexts. Always close your tags explicitly:
<table>
<tr>
<td>Cell content</td>
</tr>
</table>
<div>More content</div>
How to debug
If the error location isn’t obvious, work through these steps:
- Check the line number reported by the validator and look at what element the <div> is nested inside.
- Look for missing closing tags above the flagged line — a missing </td>, </li>, </div>, or </p> is often the real culprit.
- Verify the parent element’s content model — check whether that parent is allowed to contain a <div> by consulting the MDN element reference.
- Use your browser’s DevTools to inspect the actual DOM. If the browser moved or removed your <div>, the DOM tree will differ from your source HTML, helping you spot where the parser lost sync.
The <head> element is the container for document metadata — things like the <title>, <meta> tags, <link> elements, and <script> references. According to the HTML specification, the <head> must be the first child element of <html> and must appear exactly once. When the browser’s parser encounters a second <head> tag, or a <head> tag after the <body> has already opened, it treats it as a “stray” start tag because it violates the expected document structure.
This issue commonly arises in several situations:
- Duplicate <head> sections — often caused by copy-paste errors, template includes, or server-side rendering that injects a second <head> block.
- <head> placed inside <body> — this can happen when restructuring a page or when a component or partial template incorrectly includes its own <head>.
- Missing or misplaced closing tags — if you forget to close the <head> with </head> or accidentally close <html> early, subsequent tags may end up in unexpected positions.
This matters because browsers handle stray <head> tags inconsistently. Most modern browsers will silently ignore a second <head> and attempt to process its children as if they were part of <body>, which means your metadata (like <meta> charset declarations, stylesheets, or scripts) may not be recognized properly. This can lead to broken styling, encoding issues, missing SEO metadata, and unpredictable behavior across different browsers.
Examples
Duplicate <head> sections
A common mistake is having two <head> blocks in the same document:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<head>
<meta name="description" content="My description">
</head>
<body>
<p>Hello world</p>
</body>
</html>
The second <head> triggers the stray start tag error. Merge everything into a single <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<meta name="description" content="My description">
</head>
<body>
<p>Hello world</p>
</body>
</html>
<head> placed inside <body>
This often happens when a template partial or component includes its own <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<head>
<link rel="stylesheet" href="extra.css">
</head>
<p>Hello world</p>
</body>
</html>
Move the metadata into the existing <head> section:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<link rel="stylesheet" href="extra.css">
</head>
<body>
<p>Hello world</p>
</body>
</html>
<head> appearing after <body>
Sometimes a <head> ends up after the closing </body> tag, particularly in dynamically assembled pages:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
<head>
<meta charset="utf-8">
</head>
</html>
Again, the fix is to consolidate everything into the single, correctly placed <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
Tip for template-based systems
If you use a templating engine, static site generator, or CMS, check that only your base layout defines the <head> element. Partials and components should inject content into the existing <head> using the templating system’s block or slot mechanism, rather than wrapping their metadata in a new <head> tag. Search the final rendered HTML output for all occurrences of <head to verify there is only one.
The <html> element serves as the root of an HTML document. According to the HTML specification, there can only be one root element, and it must contain exactly one <head> element followed by one <body> element. When the browser’s parser encounters a second <html> start tag, it doesn’t know what to do with it — the tag is considered “stray” because it appears in a context where it is not expected or allowed.
This error typically occurs in a few common scenarios:
- Copy-paste mistakes — When copying HTML from another file, you may accidentally paste an entire document (including its <html> tag) inside an existing document.
- Template or include errors — Server-side includes, template engines, or component-based frameworks may inject a full HTML document structure (with its own <html> tag) into a page that already has one.
- Merging files incorrectly — Combining multiple HTML files without removing the structural tags from the inner files.
- Accidental duplication — Simply having a duplicate <html> tag due to a typo or editing oversight.
A stray <html> tag signals a malformed document structure. Browsers will attempt to recover by ignoring the duplicate tag, but the intent behind the markup becomes ambiguous. This can lead to unpredictable rendering, broken styles, or scripts that fail to target elements correctly. It also harms accessibility, as screen readers and other assistive technologies rely on a well-formed document tree to interpret content.
To fix this issue, search your HTML source for all instances of <html and ensure only one exists — at the very top of the document, right after the <!DOCTYPE html> declaration. If you find a second one, remove it along with any corresponding duplicate </html>, <head>, </head>, <body>, and </body> tags that came with it, keeping only the actual content you need.
Examples
Incorrect: Duplicate <html> tag from pasted content
This example shows a full HTML document accidentally embedded inside another, which produces the stray start tag error:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Welcome</h1>
<!-- Accidentally pasted another full document -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Other Page</title>
</head>
<body>
<p>This content was pasted from another file.</p>
</body>
</html>
</body>
</html>
Correct: Single <html> element with merged content
Remove the duplicate document structure and keep only the content you need:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Welcome</h1>
<!-- Only the relevant content from the other file -->
<p>This content was pasted from another file.</p>
</body>
</html>
Incorrect: Accidental duplicate <html> tag
Sometimes the duplication is a simple typo:
<!DOCTYPE html>
<html lang="en">
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Correct: Single <html> tag
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Checking template-based projects
If you use a templating system (e.g., PHP includes, Jinja2, Handlebars, or similar), make sure your partials and includes contain only content fragments — not full document structures. For example, an included partial should look like this:
<!-- partial: sidebar.html — no <html>, <head>, or <body> tags -->
<aside>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</aside>
The key rule is simple: every HTML document must have exactly one <html> element. If the validator reports a stray start tag, trace it back to its source — whether that’s a copy-paste error, a template include, or a simple duplication — and remove it.
The <link> element is used to define relationships between the current document and external resources — most commonly stylesheets, favicons, and preloaded assets. According to the HTML specification, <link> elements belong in the <head> section of a document (with a narrow exception for body-ok link types like certain rel="stylesheet" uses, though validators still expect them in the <head> for clarity and correctness).
This error typically happens in a few common scenarios:
- A <link> tag is accidentally placed inside the <body> element.
- A <link> tag appears after the closing </head> tag but before the <body> tag.
- A <link> tag is placed after the closing </html> tag, often by a CMS, template engine, or plugin injecting code at the end of the document.
- The </head> tag is missing or misplaced, causing the browser to implicitly close the <head> before reaching the <link>.
When the validator encounters a <link> element outside its expected context, it reports it as a “stray” start tag — meaning the element has been found somewhere it doesn’t belong.
Why this matters
Standards compliance: The HTML specification defines <link> as metadata content that belongs in <head>. Placing it elsewhere produces invalid HTML.
Unpredictable behavior: Browsers will attempt to handle misplaced <link> elements, but the behavior can be inconsistent. A stylesheet <link> found in the <body> may trigger a flash of unstyled content (FOUC) as the browser re-renders the page after discovering the new stylesheet.
Performance: Stylesheets linked from the <head> are discovered early during parsing, allowing the browser to fetch and apply them before rendering begins. Misplaced <link> elements can delay resource loading and degrade the user experience.
Maintainability: Keeping all <link> elements in the <head> makes the document structure predictable and easier for other developers to maintain.
How to fix it
- Locate the stray <link> element — the validator will indicate the line number where the issue occurs.
- Move it into the <head> section — place it after the opening <head> tag and before the closing </head> tag.
- Check that your </head> tag exists and is in the right place — a missing or misplaced </head> can cause elements you thought were in the head to actually end up in the body.
- Review template or CMS output — if you use a static site generator, CMS, or framework, check that plugins or includes aren’t injecting <link> tags outside the <head>.
Examples
❌ <link> placed inside the <body>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<link rel="stylesheet" href="css/app.css">
<h1>Hello</h1>
</body>
</html>
❌ <link> placed after the closing </html> tag
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
<link rel="stylesheet" href="css/app.css">
❌ Missing </head> causes <link> to become stray
In this example, the </head> tag is missing. The browser encounters the <body> tag and implicitly closes the <head>, but the <link> after it becomes stray content between the implicit head closure and the body.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<body>
<link rel="stylesheet" href="css/app.css">
<h1>Hello</h1>
</body>
</html>
✅ Correct: all <link> elements inside <head>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<link rel="stylesheet" href="css/app.css">
<link rel="icon" href="favicon.ico">
</head>
<body>
<h1>Hello</h1>
</body>
</html>
All <link> elements are placed within the <head> section, the </head> closing tag is present, and the document structure is clean and valid.
The “stray start tag” terminology means the HTML parser encountered a <noscript> element in a location where no element should exist. This typically happens when the tag appears between </head> and <body>, after </body>, after </html>, or when a preceding markup error has caused the parser to close the <body> prematurely, leaving the <noscript> orphaned outside any valid container.
According to the WHATWG HTML living standard, <noscript> is permitted in two contexts: inside <head> (where it can only contain <link>, <style>, and <meta> elements) and inside <body> as a flow content element (where it can contain any content normally allowed in its parent). When found anywhere else, the parser treats it as a “stray” tag because it has no valid parent to attach to.
This matters because stray elements lead to unpredictable behavior across browsers. While most browsers attempt error recovery, the resulting DOM may not match your intentions. The fallback content inside a stray <noscript> may be silently discarded or rendered incorrectly, defeating its purpose of providing an accessible experience for users without JavaScript.
A common cause is markup generated by third-party tools like analytics platforms or tag managers. These snippets often instruct you to paste a <noscript> tag “immediately after the opening <body> tag,” but if pasted in the wrong location — or if a templating system places it outside <body> — the error occurs.
Another frequent cause is unclosed elements earlier in the document. If a tag above the <noscript> is malformed, the parser may implicitly close the <body>, making subsequent elements stray. In these cases, fixing the earlier error resolves the <noscript> issue as well.
How to fix it
- Ensure <noscript> is inside <head> or <body> — never between them, before <html>, or after </html>.
- When inside <head>, only include <link>, <style>, or <meta> elements within it.
- When inside <body>, use it like any other block-level element — it can contain paragraphs, divs, images, etc.
- Check for unclosed tags above the <noscript> that might cause the parser to prematurely exit <body>.
Examples
Stray <noscript> after closing </body>
This is the most common scenario, often caused by pasting a tracking snippet in the wrong place:
<!-- ❌ Incorrect: noscript is outside body -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
</body>
<noscript>
<p>Please enable JavaScript.</p>
</noscript>
</html>
Move it inside <body>:
<!-- ✅ Correct: noscript is inside body -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
<noscript>
<p>Please enable JavaScript.</p>
</noscript>
</body>
</html>
Stray <noscript> between </head> and <body>
<!-- ❌ Incorrect: noscript is between head and body -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<noscript>
<iframe src="https://example.com/ns.html"></iframe>
</noscript>
<body>
<p>Content here.</p>
</body>
</html>
Place it at the top of <body> instead:
<!-- ✅ Correct: noscript is inside body -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<noscript>
<iframe src="https://example.com/ns.html" title="Tracking fallback"></iframe>
</noscript>
<p>Content here.</p>
</body>
</html>
Using <noscript> inside <head>
When placed in <head>, <noscript> can only contain <link>, <style>, or <meta> elements — not block content like <p> or <iframe>:
<!-- ❌ Incorrect: p is not allowed in noscript inside head -->
<head>
<title>My Page</title>
<noscript>
<p>Enable JavaScript!</p>
</noscript>
</head>
Either use only permitted elements in <head>, or move the <noscript> to <body>:
<!-- ✅ Correct: style is allowed in noscript inside head -->
<head>
<title>My Page</title>
<noscript>
<style>
.js-only { display: none; }
.nojs-message { display: block; }
</style>
</noscript>
</head>
Stray <noscript> caused by an unclosed element
Sometimes the real problem is an earlier unclosed tag. The parser implicitly closes <body>, making the <noscript> stray:
<!-- ❌ Incorrect: unclosed <div> causes parser confusion -->
<body>
<div>
<p>Some content</p>
<!-- missing </div> causes cascade of errors -->
<noscript>
<p>JavaScript is required.</p>
</noscript>
</body>
Fix the unclosed element, and the <noscript> error resolves:
<!-- ✅ Correct: div is properly closed -->
<body>
<div>
<p>Some content</p>
</div>
<noscript>
<p>JavaScript is required.</p>
</noscript>
</body>
In a valid HTML document, all content must reside within the <html> element, and specifically within either <head> or <body>. The HTML parser expects a well-defined structure: <!DOCTYPE html>, then <html>, containing <head> and <body>. When a <script> tag appears outside this hierarchy — for example, after the closing </html> tag — the validator reports it as a “stray start tag” because it has no valid parent in the document tree.
This is a common issue that arises in a few ways. Sometimes developers accidentally place a script after </body> or </html>, thinking it will still execute. Other times, template systems or CMS platforms inject scripts at the end of the output without ensuring they’re inside <body>. While browsers are forgiving and will typically still execute the script, relying on this error-recovery behavior leads to non-standard markup and unpredictable DOM placement.
Why this matters
- Standards compliance: The HTML specification requires all elements to be properly nested within the document structure. A <script> outside <html> violates this requirement.
- Predictable DOM: When a browser encounters a stray <script>, it must use error recovery to determine where to place it in the DOM. Different browsers may handle this differently, leading to inconsistencies.
- Maintainability: Invalid markup can cause confusing debugging scenarios, especially when JavaScript relies on DOM structure or ordering.
How to fix it
Move the <script> element inside either <head> or <body>:
- Place it in <head> if the script needs to load before the page content renders (configuration, analytics setup, etc.). Consider using the defer or async attribute for external scripts to avoid blocking rendering.
- Place it at the end of <body> (just before </body>) if the script interacts with DOM elements, which is a common and recommended pattern.
Examples
Incorrect: script after closing </html> tag
This triggers the “Stray start tag script” error because the <script> is outside the document structure entirely.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
<script>
console.log("This is stray!");
</script>
Incorrect: script between </head> and <body>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<script>
console.log("Misplaced script");
</script>
<body>
<p>Hello world</p>
</body>
</html>
Correct: script in the <head>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<script>
console.log("Hello from the head");
</script>
</head>
<body>
<p>Hello world</p>
</body>
</html>
Correct: script at the end of <body>
This is the most common and recommended placement for scripts that interact with the page.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
<script>
console.log("Hello from the body");
</script>
</body>
</html>
Correct: external script with defer in <head>
Using defer lets you place the script in <head> while ensuring it executes after the DOM is fully parsed, giving you the best of both worlds.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<script src="app.js" defer></script>
</head>
<body>
<p>Hello world</p>
</body>
</html>
The word “stray” in this error message means the validator encountered a start tag in a place where no element of that kind is allowed according to the HTML specification. The <section> element is flow content, so it must appear inside the <body> element (or inside another element that accepts flow content, such as <main>, <article>, <div>, etc.). When the validator sees <section> somewhere it can’t legally exist, it flags it as “stray.”
There are several common causes for this error:
- Content placed after </body> or </html>: The most frequent cause. Extra markup exists beyond the closing tags of the document body.
- Premature closing of the <body>: An extra or misplaced </body> tag earlier in the document causes the browser to consider the body closed, making any subsequent <section> stray.
- Nesting inside elements that don’t accept flow content: Placing <section> directly inside a <p>, <span>, <a>, or other phrasing-content-only element. Since these elements can’t contain block-level flow content, the browser implicitly closes the parent, leaving <section> in an invalid position.
- Malformed or unclosed tags: Earlier syntax errors — like a missing closing > on a tag — can shift the parser’s understanding of the document tree, causing downstream elements to appear stray.
This matters because browsers use error recovery when they encounter stray elements, and different browsers may handle the recovery differently. Your content could end up outside the visible document, be rendered inconsistently, or cause accessibility tools to misinterpret the page structure. Fixing this error ensures predictable rendering and a well-formed document.
Examples
Stray <section> after the closing </body> tag
This is the most common scenario. Content placed after </body> has nowhere valid to go:
<!-- ❌ Incorrect: section appears after </body> -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<h1>Welcome</h1>
<p>Some content.</p>
</body>
<section>
<h2>About</h2>
<p>This section is stray.</p>
</section>
</html>
Move the <section> inside the <body>:
<!-- ✅ Correct: section is inside <body> -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<h1>Welcome</h1>
<p>Some content.</p>
<section>
<h2>About</h2>
<p>This section is properly placed.</p>
</section>
</body>
</html>
Extra </body> tag causing a premature close
A duplicate closing tag can trick the parser into ending the body early:
<!-- ❌ Incorrect: extra </body> causes section to become stray -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<div>
<p>Main content.</p>
<!-- accidental extra closing tag -->
</div>
<section>
<h2>Updates</h2>
<p>This is now stray.</p>
</section>
</body>
</html>
Remove the extra </body> tag:
<!-- ✅ Correct: single </body> at the end -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<div>
<p>Main content.</p>
</div>
<section>
<h2>Updates</h2>
<p>This is correctly placed now.</p>
</section>
</body>
</html>
Nesting <section> inside a <p> element
The <p> element only accepts phrasing content. When the parser encounters a <section> inside a <p>, it implicitly closes the <p> first, which can leave the <section> in an unexpected position:
<!-- ❌ Incorrect: section nested inside a paragraph -->
<p>
Introduction text.
<section>
<h2>Details</h2>
<p>More info here.</p>
</section>
</p>
Separate the paragraph and section into siblings:
<!-- ✅ Correct: section is a sibling, not a child of <p> -->
<p>Introduction text.</p>
<section>
<h2>Details</h2>
<p>More info here.</p>
</section>
Unclosed tag causing downstream errors
A missing closing angle bracket on an earlier element can corrupt the parser’s view of the entire document tree:
<!-- ❌ Incorrect: missing > on the </div causes parsing issues -->
<body>
<div>
<p>Content here.</p>
</div
<section>
<h2>Topics</h2>
<p>This may be flagged as stray.</p>
</section>
</body>
Fix the malformed tag:
<!-- ✅ Correct: properly closed </div> -->
<body>
<div>
<p>Content here.</p>
</div>
<section>
<h2>Topics</h2>
<p>No longer stray.</p>
</section>
</body>
How to debug this issue
- Check the line number reported by the validator and look at what comes before the <section> tag — the problem is usually above it, not at the <section> itself.
- Search for extra closing tags like </body>, </html>, or </div> that might prematurely close a container.
- Verify parent elements — make sure <section> isn’t nested inside <p>, <span>, <a>, <button>, or other elements that only accept phrasing content.
- Use proper indentation to make the document hierarchy visually clear. Misplaced tags are much easier to spot in well-formatted code.
- Revalidate after each fix, since correcting one stray tag error often resolves multiple related warnings.
The “Stray start tag style“ error occurs when the HTML parser encounters a <style> element somewhere it doesn’t belong according to the HTML specification. The most common causes are:
- A <style> element placed after the closing </body> tag or after the closing </html> tag.
- A <style> element accidentally placed inside an element like <p>, <span>, or <a> that only accepts phrasing content and not <style> in that context.
- A <style> element appearing in the <body> without being a valid child in that context (though the HTML living standard does allow <style> in the <body> in certain conditions).
According to the WHATWG HTML living standard, the <style> element is primarily expected inside the <head> section. While the spec does technically allow <style> in the <body> where metadata content is expected (such as within a <noscript> element that is a child of <head>), placing it in the <head> is the most reliable and universally valid approach.
When a <style> tag appears after </body> or </html>, the browser’s error-recovery behavior kicks in. Browsers will still try to apply the styles, but you’re relying on undefined recovery behavior rather than the specification. This can lead to inconsistent rendering, makes the document harder to maintain, and signals structural problems in your HTML.
This issue commonly arises when content management systems, JavaScript frameworks, or copy-paste mistakes inject styles at the end of a document. It can also happen when template includes or server-side rendering place <style> blocks in unexpected locations.
To fix this issue, move the <style> element into the <head> section. Alternatively, consider moving the CSS into an external stylesheet linked via a <link> element, which is generally the preferred approach for maintainability and caching.
Examples
Incorrect: <style> after the closing </body> tag
This is the most common scenario that triggers the error. The <style> element is “stray” because it appears outside the <body> and <head>:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
<style>
p {
color: green;
}
</style>
</html>
Incorrect: <style> after the closing </html> tag
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
<style>
p {
color: green;
}
</style>
Incorrect: <style> nested inside a <p> element
The <p> element only accepts phrasing content, so a <style> element here may trigger the stray tag error:
<p>
<style>
.highlight { color: red; }
</style>
Some highlighted text.
</p>
Correct: <style> inside the <head>
Move all <style> elements into the <head> section:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<style>
p {
color: green;
}
.highlight {
color: red;
}
</style>
</head>
<body>
<p>Hello world</p>
<p class="highlight">Important text.</p>
</body>
</html>
Correct: using an external stylesheet instead
For better separation of concerns, caching, and maintainability, use an external stylesheet:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p>Hello world</p>
</body>
</html>
If you have multiple <style> blocks scattered throughout your document, consolidate them all into a single <style> element in the <head>, or better yet, move them into an external .css file. This ensures valid HTML, predictable rendering across browsers, and cleaner document structure.
The HTML specification defines a strict nesting hierarchy for table elements. A <td> (table data cell) must be a direct child of a <tr> (table row), and that <tr> must in turn live inside a <table>, <thead>, <tbody>, or <tfoot>. When the browser’s parser encounters a <td> in an unexpected location, it considers it a “stray” start tag — meaning the element has no valid place in the current parsing context.
This error commonly occurs in several scenarios:
- A <td> is placed directly inside a <table> without a wrapping <tr>.
- A <td> is placed directly inside <thead>, <tbody>, or <tfoot> without a <tr>.
- A <td> appears completely outside of any table structure, such as inside a <div> or the document <body>.
- A <tr> tag was accidentally deleted or misspelled during editing, leaving its <td> children orphaned.
Why this matters
Browser inconsistency: Browsers use error-recovery algorithms to handle invalid markup, but they may handle stray table cells differently. Some browsers might silently insert an implicit <tr>, while others might move the content outside the table entirely. This leads to unpredictable rendering across browsers.
Accessibility: Screen readers and assistive technologies rely on proper table semantics to navigate and announce cell content. A stray <td> breaks the logical row-and-column relationship, making the data difficult or impossible for assistive technology users to interpret correctly.
Maintainability: Invalid nesting makes your markup harder to understand, debug, and style with CSS. Table-specific CSS selectors and properties may not behave as expected when the DOM structure is malformed.
How to fix it
- Locate every <td> element flagged by the validator.
- Ensure it is a direct child of a <tr> element.
- Ensure that <tr> is itself inside a <table>, <thead>, <tbody>, or <tfoot>.
- If the <td> was outside a table entirely, either wrap it in a full table structure or replace it with a more appropriate element like a <div> or <span>.
Examples
<td> directly inside <table> without <tr>
This is the most common cause. The <td> elements are children of <table> but lack a wrapping <tr>:
<!-- ❌ Bad: td is a direct child of table -->
<table>
<td>Name</td>
<td>Email</td>
</table>
Wrap the cells in a <tr>:
<!-- ✅ Good: td is inside a tr -->
<table>
<tr>
<td>Name</td>
<td>Email</td>
</tr>
</table>
<td> directly inside <tbody> without <tr>
<!-- ❌ Bad: td is a direct child of tbody -->
<table>
<tbody>
<td>Alice</td>
<td>alice@example.com</td>
</tbody>
</table>
<!-- ✅ Good: td is wrapped in a tr inside tbody -->
<table>
<tbody>
<tr>
<td>Alice</td>
<td>alice@example.com</td>
</tr>
</tbody>
</table>
<td> used outside any table context
Sometimes a <td> ends up outside a table entirely, perhaps from a copy-paste error or a templating mistake:
<!-- ❌ Bad: td has no table ancestor -->
<div>
<td>Some content</td>
</div>
If you intended to display content in a non-tabular layout, use an appropriate element instead:
<!-- ✅ Good: use a span or div for non-tabular content -->
<div>
<span>Some content</span>
</div>
Missing or misspelled <tr> tag
A typo can leave <td> elements orphaned:
<!-- ❌ Bad: opening tr tag is misspelled -->
<table>
<t>
<td>Price</td>
<td>$9.99</td>
</t>
</table>
<!-- ✅ Good: correct tr element -->
<table>
<tr>
<td>Price</td>
<td>$9.99</td>
</tr>
</table>
Complete table with proper structure
For reference, here is a well-structured table using <thead>, <tbody>, <th>, and <td> — all correctly nested:
<table>
<thead>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Widget</td>
<td>$4.99</td>
</tr>
<tr>
<td>Gadget</td>
<td>$14.99</td>
</tr>
</tbody>
</table>
Ready to validate your sites?
Start your free trial today.