HTML Guides for non-space characters
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 HTML specification defines a strict content model for tables. A <table> element can only contain <caption>, <colgroup>, <thead>, <tbody>, <tfoot>, and <tr> as direct children. A <tr> element can only contain <td> and <th> elements. When text or inline elements like <span>, <a>, or <strong> appear directly inside any of these table-structural elements, they violate the content model and trigger this validation error.
This matters for several reasons. Browsers handle misplaced table content inconsistently — some will silently move the text before the table, others may discard it, and some may attempt to create anonymous table cells. This leads to unpredictable layouts across browsers and devices. Screen readers rely on correct table structure to navigate cells and announce row/column relationships, so misplaced content can confuse assistive technology users. Additionally, any text placed directly inside a <tr> but outside a cell is technically not part of any row/column structure, making it semantically meaningless in the table context.
Common causes of this error include:
- Accidentally placing text between <tr> and <td> tags
- Placing a heading or paragraph directly inside a <table> (use <caption> instead for table titles)
- Using non-breaking spaces ( ) or other characters directly inside <table> or <tr> for spacing
- Incorrectly nesting non-table elements like <div>, <p>, or <form> as direct children of <table> or <tr>
Examples
Text directly inside a table row
<!-- ❌ Wrong: text is a direct child of <tr> -->
<table>
<tr>
Hello World
<td>First Cell</td>
<td>Second Cell</td>
</tr>
</table>
<!-- ✅ Fixed: text is wrapped in a <td> -->
<table>
<tr>
<td>Hello World</td>
<td>First Cell</td>
<td>Second Cell</td>
</tr>
</table>
Text directly inside a table element
<!-- ❌ Wrong: heading and spacing text placed directly in <table> -->
<table>
Monthly Sales Report
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
</table>
<!-- ✅ Fixed: use <caption> for table titles -->
<table>
<caption>Monthly Sales Report</caption>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
</table>
Non-breaking spaces used for spacing
<!-- ❌ Wrong: directly inside <tr> -->
<table>
<tr>
<td>Data</td>
</tr>
</table>
<!-- ✅ Fixed: use CSS for spacing, or place content in a cell -->
<table>
<tr>
<td>Data</td>
</tr>
</table>
Inline elements directly inside a table
<!-- ❌ Wrong: <a> tag directly inside <table> -->
<table>
<a href="/details">View details</a>
<tr>
<td>Item 1</td>
<td>$10.00</td>
</tr>
</table>
<!-- ✅ Fixed: move the link into a cell or outside the table -->
<table>
<tr>
<td>Item 1</td>
<td>$10.00</td>
<td><a href="/details">View details</a></td>
</tr>
</table>
Content between table sections
<!-- ❌ Wrong: text between <thead> and <tbody> -->
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
No results found
<tbody>
<tr>
<td>—</td>
</tr>
</tbody>
</table>
<!-- ✅ Fixed: place the message inside a cell -->
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>No results found</td>
</tr>
</tbody>
</table>
The <!DOCTYPE html> declaration is required by the HTML specification as the first non-whitespace content in any HTML document. It instructs the browser to render the page in standards mode, which means the browser follows modern CSS and HTML specifications faithfully. When the doctype is missing or preceded by other content, browsers fall back to quirks mode — a legacy rendering mode that emulates old browser behaviors and can cause inconsistent layout, box model differences, and other subtle bugs across browsers.
This error is triggered in several common scenarios:
- The <!DOCTYPE html> declaration is completely absent from the file.
- Text, HTML tags, or other non-space characters appear before the doctype.
- A Byte Order Mark (BOM) or invisible characters were inadvertently inserted before the doctype by a text editor.
- Server-side code (such as PHP or template includes) outputs content before the doctype.
- An XML processing instruction like <?xml version="1.0"?> precedes the doctype (this is unnecessary in HTML5).
Beyond triggering quirks mode, a missing or misplaced doctype breaks standards compliance and can cause real-world rendering issues. For example, in quirks mode, box-sizing defaults differ, table elements don’t inherit font sizes properly, and percentage-based heights may not resolve correctly. These problems can be difficult to debug because they only manifest in certain browsers or under specific conditions.
How to Fix
- Open your HTML file and make sure the very first line is <!DOCTYPE html> with nothing before it — no whitespace characters, no text, no comments, and no BOM.
- Check for invisible characters. If you copied content from another source or use a text editor that inserts a BOM, open the file in a hex editor or use your editor’s “show invisible characters” feature to confirm nothing precedes the doctype.
- Check server-side scripts. If you use PHP, ASP, or a templating engine, make sure no output (including blank lines or spaces outside script tags) is emitted before <!DOCTYPE html>.
- Remove legacy doctypes or XML declarations. In HTML5, the only doctype you need is <!DOCTYPE html>. Older doctypes like <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ...> are valid but unnecessary, and XML processing instructions should not be used in HTML documents.
Examples
Missing doctype
This document has no doctype at all, which triggers the error:
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Text before the doctype
Stray text or content before the declaration also triggers the error:
Welcome to my site!
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
PHP output before the doctype
A common server-side issue where whitespace or output leaks before the doctype:
<?php include 'config.php'; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
If config.php has a closing ?> followed by a blank line, that blank line gets sent as output before the doctype. Ensure included files don’t produce unintended output.
Correct document
The doctype must be the absolute first thing in the file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Note that the doctype declaration is case-insensitive — <!DOCTYPE html>, <!doctype html>, and <!Doctype Html> are all valid. However, <!DOCTYPE html> is the conventional form recommended by the HTML living standard. A single blank line or whitespace-only line before the doctype won’t trigger this specific error (since the validator message specifies “non-space characters”), but it’s best practice to avoid any content before the declaration to keep your document clean and unambiguous.
Ready to validate your sites?
Start your free trial today.