HTML Guides for text not allowed
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.
A <details> element can hold text only after its <summary>, so any text before the <summary>, even an invisible character, is invalid.
The content model of <details> is one <summary> element followed by flow content, which means the <summary> has to come first. Spaces, tabs and line breaks between <details> and <summary> are fine. Any other character counts as text, and text in that position breaks the rule. Text after the <summary> is allowed, because it's part of the content the widget shows when it opens.
Invisible characters cause this error often. Pasting from a word processor or a rich text editor can leave a non-breaking space ( ) or a zero-width space (​, U+200B) right after the opening <details> tag. The page looks normal, but the validator still finds text there. Search the source for those characters and delete them.
If the text is meant as the label, move it into the <summary>. If it's part of the content, put it after the <summary>. A <details> with no <summary> at all also triggers this error, together with one saying the required <summary> child is missing.
Invalid example
<details>
Shipping information
<summary>Shipping</summary>
<p>Orders ship within two days.</p>
</details>
Valid example
<details>
<summary>Shipping information</summary>
<p>Orders ship within two days.</p>
</details>
Text content cannot be placed directly inside an ol element. All text within an ordered list must be wrapped in li elements.
The ol element accepts only li, script, and template elements as children. Any bare text node placed directly between <ol> and </ol> (or between </li> and <li>) is invalid. This includes whitespace-only text nodes in some edge cases, but the validator typically flags visible text content.
This error often appears when list items are missing their <li> tags, or when extra text (like a heading or description) is placed inside the ol instead of before or after it.
Invalid example
<ol>
Some introductory text
<li>First item</li>
<li>Second item</li>
</ol>
Valid example
Move the text outside the ol, or wrap each piece of text in an li element:
<p>Some introductory text</p>
<ol>
<li>First item</li>
<li>Second item</li>
</ol>
Direct text nodes inside select are not permitted content. Browsers typically ignore or mangle that text, leading to inconsistent rendering and confusing experiences for screen reader users. It also breaks conformance, which can impact maintainability and automated tooling. The right approach is to keep instructional text in a corresponding label, or provide a non-selectable prompt using a disabled, selected option. Group labels must be provided with optgroup elements, not free text.
To fix it, remove any raw text inside the select. If you need a prompt, add a first option with value="" and disabled selected hidden for a placeholder-like experience, or rely on a visible label. Ensure all selectable items are wrapped in option, and any grouping uses optgroup with its label attribute. Always associate the select with a label via for/id for accessibility.
Examples
Triggers the error (text node inside select)
<select>
Please select an option:
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
Correct: move instructions to a label
<label for="flavor">Please select a flavor:</label>
<select id="flavor" name="flavor">
<option value="vanilla">Vanilla</option>
<option value="chocolate">Chocolate</option>
</select>
Correct: provide a non-selectable prompt inside select
<label for="country">Country</label>
<select id="country" name="country" required>
<option value="" disabled selected hidden>Select a country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>
Correct: use optgroup for grouping, not free text
<label for="city">City</label>
<select id="city" name="city">
<optgroup label="USA">
<option value="nyc">New York</option>
<option value="la">Los Angeles</option>
</optgroup>
<optgroup label="Canada">
<option value="toronto">Toronto</option>
<option value="vancouver">Vancouver</option>
</optgroup>
</select>
Correct: full document (for context)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Select without stray text</title>
</head>
<body>
<form>
<label for="size">Choose a size:</label>
<select id="size" name="size">
<option value="" disabled selected hidden>Select a size</option>
<option value="s">Small</option>
<option value="m">Medium</option>
<option value="l">Large</option>
</select>
</form>
</body>
</html>
Tips:
- Put instructions in a
labelor surrounding text, not insideselect. - Every choice must be an
option; useoptgroupwithlabelto name groups. - For placeholders, prefer a disabled, selected first
option; avoid raw text nodes.
An <svg> element can contain child elements and the whitespace between them, but no text of its own.
The most common cause is a typo in the start tag. An extra >, as in <svg viewBox="0 0 24 24">>, closes the tag and leaves the second > behind as a text character inside the SVG. The validator also reports this error for a entity, a stray word, or fallback text such as "Close" written between the child elements. Line breaks and indentation between elements are fine.
Browsers don't draw text that sits directly inside <svg>, so the graphic looks correct and the mistake is easy to miss. To show text in the graphic, put it in a <text> element. To give the graphic an accessible name, add a <title> element inside the <svg>.
Text placed directly inside a <g> or another SVG container triggers the same kind of error, naming that element instead of svg.
Invalid example: extra > in the start tag
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">>
<path d="M5 15.5L12 8.5L19 15.5" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
Valid example
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M5 15.5L12 8.5L19 15.5" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
Invalid example: text used as a label
<svg viewBox="0 0 24 24" width="24" height="24">
Close
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" />
</svg>
Valid example: label in a title element
<svg viewBox="0 0 24 24" width="24" height="24" role="img">
<title>Close</title>
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" />
</svg>
According to the HTML specification, the content model for <ul> is strictly limited to zero or more <li> elements. Any text node placed directly inside the <ul> violates this rule, even if it seems harmless or invisible. Browsers may still render the page, but the resulting DOM structure is technically invalid and can lead to unpredictable behavior across different browsers and assistive technologies.
This matters for accessibility because screen readers rely on proper list structure to announce the number of items and allow users to navigate between them. Stray text nodes inside a <ul> can confuse these tools, causing list items to be miscounted or the text to be read in an unexpected context.
There are several common scenarios that trigger this error:
Loose text used as a list title. Developers sometimes place a heading or label directly inside the <ul> to describe the list. This text must be moved outside the list element.
Stray or other entities between list items. This often happens in templating systems or when code is concatenated, where characters or other text nodes end up between <li> elements. These should be removed entirely, since spacing between list items should be controlled with CSS.
Accidentally placing inline content without wrapping it in <li>. Sometimes content that should be a list item is simply missing its <li> wrapper.
Examples
❌ Text used as a list title inside <ul>
<ul>
Fruits
<li>Apple</li>
<li>Orange</li>
<li>Banana</li>
</ul>
The word "Fruits" is a text node directly inside the <ul>, which is not allowed.
✅ Move the title outside the list
<h3>Fruits</h3>
<ul>
<li>Apple</li>
<li>Orange</li>
<li>Banana</li>
</ul>
Using a heading before the list is semantically clear. You can also use a <p> or <span> if a heading isn't appropriate.
❌ entities between list items
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
Each is a text node sitting directly inside the <ul>, triggering the error.
✅ Remove the entities and use CSS for spacing
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
ul li {
margin-bottom: 0.5em;
}
Any visual spacing between list items should be handled with CSS margin or padding, not with HTML entities.
❌ Unwrapped content that should be a list item
<ul>
<li>Milk</li>
Eggs
<li>Bread</li>
</ul>
✅ Wrap the content in an <li> element
<ul>
<li>Milk</li>
<li>Eggs</li>
<li>Bread</li>
</ul>
The same rules apply to <ol> (ordered lists) and <menu> elements — their direct children must be <li> elements, and text nodes are not permitted. If your list is generated dynamically by a templating engine or JavaScript, check the output carefully for stray whitespace or text that may have been injected between list items.
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