HTML Guides for whitespace
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 id attribute uniquely identifies an element within a document, making it essential for fragment links, JavaScript targeting, CSS styling, and label associations. According to the HTML specification, an id value must contain at least one character and must not contain any ASCII whitespace. This means spaces, tabs, line feeds, carriage returns, and form feeds are all prohibited.
A common mistake is accidentally including a space in an id value, which effectively makes it look like multiple values — similar to how the class attribute works. However, unlike class, the id attribute does not support space-separated values. When a browser encounters an id with a space, behavior becomes unpredictable: some browsers may treat only the first word as the ID, while CSS and JavaScript selectors may fail entirely.
Why this matters
- Broken fragment links: A link like
<a href="#my section">won't correctly scroll to an element withid="my section"in all browsers. - JavaScript failures:
document.getElementById("my section")may not return the expected element, anddocument.querySelector("#my section")will throw a syntax error because spaces are not valid in CSS ID selectors without escaping. - CSS issues: A selector like
#my sectiontargets an element withid="my"that has a descendant<section>element — not what you intended. - Accessibility: Screen readers and assistive technologies rely on
idattributes for label associations (e.g.,<label for="...">). A brokenidcan break form accessibility.
Best practices for id values
While the HTML specification technically allows any non-whitespace character in an id, it's best practice to stick to ASCII letters, digits, hyphens (-), and underscores (_). Starting the value with a letter also ensures maximum compatibility with CSS selectors without needing escaping.
Examples
❌ Invalid: id contains a space
<div id="main content">
<p>Welcome to the page.</p>
</div>
The space between main and content makes this an invalid id.
✅ Fixed: Replace the space with a hyphen
<div id="main-content">
<p>Welcome to the page.</p>
</div>
✅ Fixed: Replace the space with an underscore
<div id="main_content">
<p>Welcome to the page.</p>
</div>
✅ Fixed: Use camelCase
<div id="mainContent">
<p>Welcome to the page.</p>
</div>
❌ Invalid: id with a space breaks label association
<label for="first name">First Name</label>
<input type="text" id="first name">
The for attribute won't properly associate with the input, breaking accessibility.
✅ Fixed: Remove whitespace from both for and id
<label for="first-name">First Name</label>
<input type="text" id="first-name">
❌ Invalid: Trailing or leading whitespace
Whitespace isn't always obvious. A trailing space or a copy-paste error can introduce invisible whitespace:
<section id="about ">
<h2>About Us</h2>
</section>
✅ Fixed: Trim all whitespace
<section id="about">
<h2>About Us</h2>
</section>
If you're generating id values dynamically (e.g., from a CMS or database), make sure to trim and sanitize the values by stripping whitespace and replacing spaces with hyphens or underscores before rendering them into HTML.
The colspan attribute of a <td> takes digits only, so a single space after the number, as in colspan="2 ", makes the value invalid.
The space usually comes from a template. In <td colspan="{{ span }} "> or <td colspan="<?php echo $span; ?> ">, the space before the closing quote ends up in the attribute, right after the number. A helper that pads numbers to a fixed width has the same effect. A space before the number (" 2") or a line break inside the quotes gets the same error. The character after "saw" is the first one that isn't a digit: a blank here, p in 2px, % in 50%. A value with markup in it, like 2><span class=, means a closing quote is missing.
The HTML standard requires colspan to be a valid non-negative integer greater than zero and no larger than 1000, which is one or more digits with nothing around them. Browsers skip leading spaces, read the digits and ignore the rest, so "2 " still spans two columns. The validator's table check counts a cell with a trailing space as one column, though, so a "table row was N columns wide" warning often appears alongside this error.
Fix the template so the closing quote comes right after the number, or trim the value before printing it.
Invalid example
<table>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Price</th>
</tr>
<tr>
<td>Notebook</td>
<td>2</td>
<td>$8</td>
</tr>
<tr>
<td colspan="2 ">Total</td>
<td>$8</td>
</tr>
</table>
Valid example
<table>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Price</th>
</tr>
<tr>
<td>Notebook</td>
<td>2</td>
<td>$8</td>
</tr>
<tr>
<td colspan="2">Total</td>
<td>$8</td>
</tr>
</table>
The coords value contains a space where the validator expects the start of a number.
An <area> element defines a region in an image map. Its coords attribute describes that region using coordinates in CSS pixels. For shape="poly", provide at least three pairs of x and y coordinates, with an even number of values.
In the example below, Rocket's HTML validator rejects the space immediately after the second comma. Write the coordinates as comma-separated numbers without spaces to avoid this parsing error. Keep the values appropriate for the selected shape.
Invalid example
<map name="floor-plan">
<area shape="poly" coords="0,0, 100,0,100,50" href="/reception" alt="Reception">
</map>
Valid example
<map name="floor-plan">
<area shape="poly" coords="0,0,100,0,100,50" href="/reception" alt="Reception">
</map>
The <label> element represents a caption for a form control. When you use the for attribute, its value must match the id of the form control it labels. According to the HTML specification, an id attribute value must not contain any whitespace characters — this includes spaces, tabs, line feeds, carriage returns, and form feeds. Since for must reference a valid ID, the same restriction applies to its value.
This error typically occurs when a developer uses a space-separated name (like "user name" or "first name") instead of a single continuous token. Browsers may fail to establish the programmatic association between the label and its form control when the for value contains whitespace. This directly impacts accessibility: screen readers rely on this association to announce the label text when a user focuses on the input. It also breaks the click-to-focus behavior where clicking a label moves focus to its associated control.
To fix this issue, replace any whitespace in the for attribute value with a valid character such as a hyphen (-), underscore (_), or camelCase. Make sure the id on the corresponding form control matches exactly.
Examples
Incorrect — whitespace in the for attribute
<form>
<label for="user name">Name</label>
<input type="text" id="user name">
</form>
The value "user name" contains a space, which makes it an invalid ID reference. The validator will report: Bad value "user name" for attribute "for" on element "label": An ID must not contain whitespace.
Correct — using an underscore instead of a space
<form>
<label for="user_name">Name</label>
<input type="text" id="user_name">
</form>
Correct — using a hyphen instead of a space
<form>
<label for="user-name">Name</label>
<input type="text" id="user-name">
</form>
Correct — using camelCase
<form>
<label for="userName">Name</label>
<input type="text" id="userName">
</form>
Incorrect — leading or trailing whitespace
Whitespace doesn't have to be in the middle of the value to trigger this error. Leading or trailing spaces also make the ID invalid:
<form>
<label for=" email">Email</label>
<input type="text" id=" email">
</form>
This can be easy to miss when values are generated dynamically or copied from another source. Trim the value to fix it:
<form>
<label for="email">Email</label>
<input type="text" id="email">
</form>
Alternative — wrapping the input inside the label
If you wrap the form control inside the <label> element, you don't need the for attribute at all. The association is implicit:
<form>
<label>
Name
<input type="text">
</label>
</form>
This approach avoids potential ID mismatches entirely, though explicit for/id pairing is often preferred for flexibility in layout and styling.
The doctype's public identifier and system identifier are written back to back, with no space between their two quoted strings.
Legacy doctypes from HTML 4.01 and XHTML 1.0 have two quoted strings after the PUBLIC keyword. The first is the public identifier, which names the DTD, such as "-//W3C//DTD XHTML 1.0 Transitional//EN". The second is the system identifier, the URL of that DTD. The HTML syntax requires whitespace between them, so a closing quote followed directly by an opening quote (//EN""http://) is a parse error. The same applies to single-quoted identifiers.
These doctypes are usually split across two lines, with the URL on the second line. A minifier or template that removes the line break without leaving a space produces this error.
Browsers recover from it: they still read both identifiers, so the page renders in the same mode as it would with the space. The legacy doctype itself is still reported, as "Almost standards mode doctype" or "Obsolete doctype". Adding a space clears this error only. Replacing the declaration with <!DOCTYPE html>, which has no identifiers, clears both.
Invalid example
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Products</title>
</head>
<body>
<p>Hello</p>
</body>
</html>
Valid example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Products</title>
</head>
<body>
<p>Hello</p>
</body>
</html>
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries