HTML Guides for id
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 with id="my section" in all browsers.
- JavaScript failures: document.getElementById("my section") may not return the expected element, and document.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 section targets an element with id="my" that has a descendant <section> element — not what you intended.
- Accessibility: Screen readers and assistive technologies rely on id attributes for label associations (e.g., <label for="...">). A broken id can 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 for attribute on a <label> element tells the browser which form control the label describes. When a user clicks or taps the label, the browser transfers focus to the associated control. For this to work, the value of for must exactly match the id of a form element such as an <input>, <textarea>, <select>, or <button>.
An empty string ("") is not a valid ID according to the HTML specification. The WHATWG HTML standard requires that an id attribute value must contain at least one character and must not contain ASCII whitespace. Since no element can have an empty-string id, a <label> with for="" can never successfully reference anything, making it both invalid markup and a broken association.
Why this matters
Accessibility: Screen readers rely on the for/id pairing to announce what a form control is for. A label with an empty for attribute creates no programmatic association, meaning assistive technology users may not know what a field is asking for. This directly impacts WCAG compliance.
Usability: A properly associated label expands the clickable area of its form control. For example, clicking a label associated with a checkbox will toggle the checkbox. An empty for attribute breaks this behavior.
Standards compliance: The W3C validator flags this because it violates the HTML specification. Keeping markup valid helps ensure consistent behavior across browsers and future-proofs your code.
How to fix
You have three options:
- Set for to a valid id: Give the associated form control a unique id and reference it in the label’s for attribute.
- Remove for and use implicit association: Wrap the form control inside the <label> element. This creates an implicit association without needing for or id at all.
- Remove the for attribute: If the label is purely decorative or not meant to be associated with a control, simply remove the empty for attribute.
Examples
❌ Empty for attribute (triggers the error)
<label for="">Username:</label>
<input type="text" name="username">
The label has no meaningful association with the input because for="" is not a valid reference.
✅ Fix: Use a valid for/id pair
<label for="username">Username:</label>
<input type="text" id="username" name="username">
The for="username" now matches id="username" on the input, creating an explicit association.
✅ Fix: Use implicit association by nesting
<label>
Username:
<input type="text" name="username">
</label>
Wrapping the input inside the <label> creates an implicit association. No for or id attributes are needed.
❌ Multiple labels with empty for attributes
<form>
<label for="">Email:</label>
<input type="email" name="email">
<label for="">Subscribe to newsletter</label>
<input type="checkbox" name="subscribe">
</form>
✅ Fixed with proper associations
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="subscribe">Subscribe to newsletter</label>
<input type="checkbox" id="subscribe" name="subscribe">
</form>
Each id must be unique within the document, and each for attribute must reference exactly one id. If your labels are generated by a framework or CMS with empty for values, check the template or component configuration to ensure proper id values are being output.
The id attribute uniquely identifies an element within a document. According to the WHATWG HTML living standard, if the id attribute is specified, its value must be non-empty and must not contain any ASCII whitespace characters. The attribute itself is optional — you don’t need to include it — but when you do, it must have a valid value. Setting id="" violates this rule because the empty string is not a valid identifier.
This issue commonly occurs when code is generated dynamically (e.g., by a templating engine or JavaScript framework) and the variable intended to populate the id value resolves to an empty string. It can also happen when developers add the attribute as a placeholder and forget to fill it in.
Why this matters
- Standards compliance: An empty id violates the HTML specification, making your document invalid.
- Accessibility: Assistive technologies like screen readers rely on id attributes to associate <label> elements with form controls. An empty id breaks this association, making forms harder to use for people who depend on these tools.
- JavaScript and CSS: Methods like document.getElementById("") and selectors like # (with no identifier) will not work as expected. An empty id can cause subtle, hard-to-debug issues in your scripts and styles.
- Browser behavior: While browsers are generally forgiving, an empty id leads to undefined behavior. Different browsers may handle it inconsistently.
How to fix it
- Assign a meaningful value: Give the id a descriptive, unique value that identifies the element’s purpose (e.g., id="country-select").
- Remove the attribute: If you don’t need the id, simply remove it from the element altogether.
- Fix dynamic generation: If a templating engine or framework is producing the empty value, add a conditional check to either output a valid id or omit the attribute entirely.
Examples
❌ Incorrect: empty id attribute
<label for="country">Country</label>
<select id="" name="country">
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>
This triggers the validation error because id="" is an empty string.
✅ Correct: meaningful id value
<label for="country">Country</label>
<select id="country" name="country">
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>
The id now has a valid, non-empty value, and the <label> element’s for attribute correctly references it.
✅ Correct: id attribute removed entirely
<label>
Country
<select name="country">
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>
</label>
If you don’t need the id, remove it. Here, the <label> wraps the <select> directly, so the for/id association isn’t needed — the implicit label works just as well.
The validator reports “Bad value “” for attribute id on element X: An ID must not be the empty string” when any element includes an empty id attribute. Per the HTML standard, id is a global attribute used as a unique document-wide identifier. An empty identifier is not a valid value and is ignored by some features, leading to hard-to-debug issues.
This matters for accessibility and interoperability. Features that depend on IDs—fragment navigation (#target), <label for>, ARIA attributes like aria-labelledby/aria-controls, and DOM APIs such as document.getElementById()—require a non-empty, unique value. Empty IDs break these links, can degrade assistive technology output, and violate conformance, which may hide bugs across browsers.
How to fix:
- If the element doesn’t need an identifier, remove the id attribute entirely.
- If it needs one, provide a non-empty, unique value, e.g., id="main-content".
- Ensure uniqueness across the page; each id must occur only once.
- Use simple, predictable tokens: avoid spaces, prefer lowercase letters, digits, hyphens, and underscores (e.g., feature-1). While the spec allows a broad range of characters, sticking to URL- and selector-friendly characters avoids pitfalls.
Examples
Example that triggers the validator error (empty id)
<div id=""></div>
Correct: remove an unnecessary empty id
<div></div>
Correct: provide a meaningful, unique id
<section id="features"></section>
Problematic label association with empty id (invalid)
<label for="">Email</label>
<input type="email" id="">
Correct label–control association
<label for="email">Email</label>
<input type="email" id="email">
Correct ARIA relationship
<h2 id="pricing-heading">Pricing</h2>
<section aria-labelledby="pricing-heading">
<p>Choose a plan.</p>
</section>
Correct fragment navigation target
<nav>
<a href="#contact">Contact</a>
</nav>
<section id="contact">
<h2>Contact us</h2>
</section>
Minimal full document (validated) demonstrating proper ids
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Valid IDs Example</title>
</head>
<body>
<main id="main-content">
<h1 id="page-title">Welcome</h1>
<p>Jump to the <a href="#details">details</a>.</p>
<section id="details">
<h2>Details</h2>
</section>
<form>
<label for="email">Email</label>
<input id="email" type="email">
</form>
</main>
</body>
</html>
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 <pattern> element lives inside <svg>, and SVG is an XML-based language. Unlike regular HTML — where id values follow relatively relaxed rules — SVG content must comply with XML 1.0 naming conventions. This means id values have stricter character and formatting requirements than you might be used to in plain HTML.
XML 1.0 Name Rules
An XML 1.0 name (used for id attributes in SVG) must follow these rules:
- First character must be a letter (A–Z, a–z) or an underscore (_).
- Subsequent characters can be letters, digits (0–9), hyphens (-), underscores (_), or periods (.).
- Spaces and special characters like !, @, #, $, %, (, ), etc. are not allowed anywhere in the name.
Common mistakes that trigger this error include starting an id with a digit (e.g., 1pattern), a hyphen (e.g., -myPattern), or a period (e.g., .dotPattern), or including characters like spaces or colons.
Why This Matters
- Standards compliance: SVG is parsed as XML in many contexts. An invalid XML name can cause parsing errors or unexpected behavior, especially when SVG is served with an XML MIME type or embedded in XHTML.
- Functionality: The <pattern> element’s id is typically referenced via url(#id) in fill or stroke attributes. An invalid id may cause the pattern reference to silently fail, leaving elements unfilled or invisible.
- Cross-browser consistency: While some browsers are lenient with invalid XML names, others are not. Using valid names ensures consistent rendering across all browsers and environments.
How to Fix
Rename the id value so it starts with a letter or underscore and contains only valid characters. If you reference this id elsewhere (e.g., in fill="url(#...)" or in CSS), update those references to match.
Examples
❌ Invalid: id starts with a digit
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="1stPattern" width="10" height="10" patternUnits="userSpaceOnUse">
<circle cx="5" cy="5" r="3" fill="blue" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#1stPattern)" />
</svg>
❌ Invalid: id starts with a hyphen
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="-stripe-bg" width="10" height="10" patternUnits="userSpaceOnUse">
<rect width="5" height="10" fill="red" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#-stripe-bg)" />
</svg>
❌ Invalid: id contains special characters
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="my pattern!" width="10" height="10" patternUnits="userSpaceOnUse">
<circle cx="5" cy="5" r="3" fill="green" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#my pattern!)" />
</svg>
✅ Valid: id starts with a letter
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="firstPattern" width="10" height="10" patternUnits="userSpaceOnUse">
<circle cx="5" cy="5" r="3" fill="blue" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#firstPattern)" />
</svg>
✅ Valid: id starts with an underscore
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="_stripe-bg" width="10" height="10" patternUnits="userSpaceOnUse">
<rect width="5" height="10" fill="red" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#_stripe-bg)" />
</svg>
✅ Valid: Using letters, digits, hyphens, and underscores
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="dot-grid_v2" width="10" height="10" patternUnits="userSpaceOnUse">
<circle cx="5" cy="5" r="3" fill="green" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#dot-grid_v2)" />
</svg>
Note that this same XML 1.0 naming rule applies to id attributes on all SVG elements — not just <pattern>. If you see similar errors on elements like <linearGradient>, <clipPath>, or <filter>, the same fix applies: ensure the id starts with a letter or underscore and uses only valid characters.
The id attribute serves as a unique identifier for a single element in the DOM. The HTML specification explicitly requires that id values be unique across the entire document. When you reuse an id, you violate this contract, and the consequences can be subtle but far-reaching.
JavaScript behavior becomes unpredictable. Methods like document.getElementById() will only return the first element with a given id, silently ignoring any duplicates. This can cause scripts to target the wrong element or fail to interact with elements you expect them to reach.
CSS selectors may not apply as intended. While most browsers will style all elements with a duplicated id, this behavior is not guaranteed by the specification and can lead to inconsistencies across browsers.
Accessibility is compromised. Screen readers and other assistive technologies rely on unique IDs to associate labels with form controls (via for/id pairing), link aria-describedby or aria-labelledby references to specific elements, and navigate fragment identifiers (anchor links). Duplicate IDs break these associations, potentially making content confusing or unusable for people relying on assistive technology.
Fragment navigation breaks. When a URL contains a hash like #section-intro, the browser scrolls to the element with that id. If multiple elements share the same id, only the first one will be targeted, which may not be the intended destination.
Common causes of duplicate IDs include copy-pasting HTML blocks without updating the id values, dynamically generating content in a loop without appending a unique suffix, and reusing template partials that contain hardcoded id attributes.
To fix this issue, audit your document for repeated id values. If multiple elements need the same identifier for styling purposes, use the class attribute instead. If the id is needed for JavaScript or ARIA references, make each value unique — for example, by appending a number or descriptive suffix.
Examples
❌ Duplicate IDs on multiple elements
<div id="card">
<h2>First Card</h2>
</div>
<div id="card">
<h2>Second Card</h2>
</div>
Both <div> elements share id="card", which triggers the validation error.
✅ Use unique IDs
<div id="card-1">
<h2>First Card</h2>
</div>
<div id="card-2">
<h2>Second Card</h2>
</div>
✅ Use class instead when you don’t need unique identification
<div class="card">
<h2>First Card</h2>
</div>
<div class="card">
<h2>Second Card</h2>
</div>
❌ Duplicate IDs break label associations
<label for="email">Work Email</label>
<input type="email" id="email" name="work_email">
<label for="email">Personal Email</label>
<input type="email" id="email" name="personal_email">
Both inputs share id="email", so the second <label> will incorrectly point to the first input. A screen reader user clicking “Personal Email” would be focused on the wrong field.
✅ Unique IDs for each label–input pair
<label for="work-email">Work Email</label>
<input type="email" id="work-email" name="work_email">
<label for="personal-email">Personal Email</label>
<input type="email" id="personal-email" name="personal_email">
❌ Duplicate IDs in dynamically repeated content
This often happens when generating HTML in a loop or reusing a template:
<section id="product">
<h2>Widget A</h2>
</section>
<section id="product">
<h2>Widget B</h2>
</section>
<section id="product">
<h2>Widget C</h2>
</section>
✅ Append a unique suffix
<section id="product-1">
<h2>Widget A</h2>
</section>
<section id="product-2">
<h2>Widget B</h2>
</section>
<section id="product-3">
<h2>Widget C</h2>
</section>
If no element actually needs to be uniquely identified, remove the id entirely and use a class or a data attribute instead.
The HTML specification requires that every id attribute value must be unique within a document. When the validator encounters the same id on two or more elements, it raises an error on the second (and subsequent) occurrences, along with a companion message — “The first occurrence of ID ‘X’ was here” — pointing to the original element. This companion message helps you quickly compare both locations and decide which one to rename or remove.
Why Duplicate IDs Are a Problem
Accessibility: Screen readers and other assistive technologies rely on unique IDs to associate <label> elements with form controls, to navigate ARIA relationships like aria-labelledby and aria-describedby, and to jump to page landmarks. When IDs are duplicated, these associations break, leaving users confused or unable to interact with the page properly.
JavaScript behavior: Methods like document.getElementById() return only the first matching element. If you intend to target the second element with a duplicated ID, your code will silently operate on the wrong one. This can lead to bugs that are difficult to track down.
CSS specificity: While #my-id selectors will style all elements with that ID in most browsers, this is non-standard behavior. Relying on it leads to fragile, unpredictable styling.
Fragment navigation: Links using href="#section" scroll to the first element with that ID. Duplicate IDs make it impossible to link to the second occurrence.
How to Fix It
- Identify the duplicates. The validator tells you the line number of the first occurrence and the line number of the duplicate. Compare both elements.
- Rename one of the IDs to something unique and descriptive. Update any corresponding references (labels, ARIA attributes, JavaScript selectors, CSS rules, and anchor links).
- Use class instead of id when you need to apply the same style or behavior to multiple elements. Classes are designed to be reused; IDs are not.
Examples
❌ Duplicate IDs trigger the error
<div id="product-card">
<h2>Widget A</h2>
<p>A useful widget.</p>
</div>
<div id="product-card">
<h2>Widget B</h2>
<p>Another useful widget.</p>
</div>
The validator will report an error on the second div and display the message “The first occurrence of ID ‘product-card’ was here” pointing to the first div.
✅ Fixed: Give each element a unique ID
<div id="product-card-a">
<h2>Widget A</h2>
<p>A useful widget.</p>
</div>
<div id="product-card-b">
<h2>Widget B</h2>
<p>Another useful widget.</p>
</div>
✅ Fixed: Use a class for shared styling or behavior
If both elements don’t need to be individually targeted, replace the id with a class:
<div class="product-card">
<h2>Widget A</h2>
<p>A useful widget.</p>
</div>
<div class="product-card">
<h2>Widget B</h2>
<p>Another useful widget.</p>
</div>
❌ Duplicate IDs breaking a label association
<label for="email">Email</label>
<input type="email" id="email" name="primary-email">
<label for="email">Backup Email</label>
<input type="email" id="email" name="backup-email">
Both labels point to for="email", but only the first input will be associated. The second label effectively has a broken link.
✅ Fixed: Unique IDs for each form control
<label for="primary-email">Email</label>
<input type="email" id="primary-email" name="primary-email">
<label for="backup-email">Backup Email</label>
<input type="email" id="backup-email" name="backup-email">
Now each <label> correctly associates with its own <input>, and both assistive technologies and JavaScript can target each field reliably.
Before HTML5, the way to create a link target within a page was to use a “named anchor” — an <a> element with a name attribute. This allowed other links to jump to that specific spot using a fragment identifier (e.g., href="#section-5"). In HTML5, the name attribute on <a> elements has been marked as obsolete. Instead, the id attribute on any element serves this purpose, making the extra <a> wrapper unnecessary.
This matters for several reasons:
- Standards compliance: Using obsolete attributes means your markup doesn’t conform to the current HTML specification, which can cause W3C validation errors.
- Cleaner markup: Named anchors add an extra element that serves no semantic purpose. Using id directly on the target element is simpler and more meaningful.
- Accessibility: Screen readers and assistive technologies work better with semantic HTML. An id on a heading or <section> provides clearer document structure than a nested anchor element.
- Browser behavior: While browsers still support name for backward compatibility, relying on obsolete features is risky as future browser versions may change or drop support.
To fix this, remove the <a name="..."> element and place an id attribute directly on the nearest appropriate container element, such as a heading (<h2>, <h3>, etc.), a <section>, or a <div>.
Examples
Incorrect: using the obsolete name attribute
<h2>
<a name="section-5">Section 5</a>
</h2>
The <a> element here exists solely to create a link target, adding unnecessary markup.
Correct: using id on the heading
<h2 id="section-5">Section 5</h2>
The id attribute on the <h2> makes it a valid fragment link target without any extra elements.
Linking to the section
Both approaches allow navigation via the same fragment URL. The link syntax doesn’t change:
<a href="#section-5">Jump to Section 5</a>
Using id on other container elements
The id attribute works on any HTML element, so you can place it wherever makes the most sense semantically:
<section id="contact-info">
<h2>Contact Information</h2>
<p>Email us at hello@example.com.</p>
</section>
Incorrect: multiple named anchors in a document
<p>
<a name="intro">Welcome to our page.</a>
</p>
<p>
<a name="conclusion">Thanks for reading.</a>
</p>
Correct: replacing all named anchors with id attributes
<p id="intro">Welcome to our page.</p>
<p id="conclusion">Thanks for reading.</p>
Remember that id values must be unique within a document — no two elements can share the same id. If you’re migrating from name attributes, check for duplicates and ensure each id is used only once.
The name attribute was historically used on img elements to reference images through JavaScript’s document.images collection or via document.getElementsByName(). In early HTML, name served as an identifier for various elements before the id attribute was widely adopted. The HTML living standard (WHATWG) now marks name as obsolete on img elements, meaning it should no longer be used in new content.
This matters for several reasons:
- Standards compliance: Using obsolete attributes means your HTML does not conform to the current specification, which can cause validation errors and may lead to unexpected behavior in future browser versions.
- Consistency: The id attribute is the universal mechanism for uniquely identifying any HTML element. Using id instead of name keeps your markup consistent and predictable.
- JavaScript and CSS targeting: Modern APIs like document.getElementById() and document.querySelector() work with id, not name on image elements. CSS selectors also target elements by id (e.g., #myImage), making id the more versatile choice.
- Fragment linking: The id attribute allows you to link directly to an element using a URL fragment (e.g., page.html#myImage), whereas the obsolete name attribute on img does not serve this purpose.
To fix this issue, simply replace name with id on your img elements. Keep in mind that id values must be unique within the entire document — no two elements can share the same id. If you have JavaScript code that references the image by name (e.g., document.images["myImage"] or document.getElementsByName("myImage")), update those references to use document.getElementById("myImage") or document.querySelector("#myImage") instead.
Examples
Incorrect: using the obsolete name attribute
<img src="photo.jpg" name="heroImage" alt="A sunset over the ocean">
This triggers the validation error because name is no longer a valid attribute on img.
Correct: using the id attribute
<img src="photo.jpg" id="heroImage" alt="A sunset over the ocean">
The name attribute is replaced with id, and the element can now be targeted with document.getElementById("heroImage") or the CSS selector #heroImage.
Updating JavaScript references
If your existing code references the image by name, update it accordingly.
Before (relying on name):
<img src="logo.png" name="siteLogo" alt="Company logo">
<script>
var logo = document.images["siteLogo"];
logo.style.border = "2px solid blue";
</script>
After (using id):
<img src="logo.png" id="siteLogo" alt="Company logo">
<script>
var logo = document.getElementById("siteLogo");
logo.style.border = "2px solid blue";
</script>
Multiple images that previously shared a name
Since id values must be unique, you cannot give the same id to multiple elements. If you previously used the same name on several images and selected them as a group, switch to a shared class instead:
<img src="slide1.jpg" class="gallery-image" alt="Mountain landscape">
<img src="slide2.jpg" class="gallery-image" alt="Forest trail">
<img src="slide3.jpg" class="gallery-image" alt="River valley">
<script>
var images = document.querySelectorAll(".gallery-image");
images.forEach(function(img) {
img.style.borderRadius = "8px";
});
</script>
This approach is standards-compliant and gives you flexible, modern element selection using class for groups and id for unique elements.
The name attribute was historically used on <option> elements in older HTML specifications, but it has been obsolete since HTML5. The WHATWG HTML Living Standard does not list name as a valid attribute for <option>. The valid attributes for <option> are disabled, label, selected, and value, in addition to the global attributes (such as id, class, style, etc.).
It’s important to understand that the name attribute on <option> never served the same purpose as name on <input> or <select>. For form submission, the browser sends the name from the parent <select> element paired with the value of the selected <option>. Putting name on individual <option> elements has no effect on form data and can mislead developers into thinking it influences form behavior.
Removing the obsolete name attribute ensures your HTML is standards-compliant, avoids confusion for developers maintaining the code, and prevents potential issues with future browser behavior. If you need to reference a specific <option> in JavaScript or CSS, use the id global attribute instead.
Examples
Incorrect: using the obsolete name attribute
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option name="dog-option" value="dog">Dog</option>
<option name="cat-option" value="cat">Cat</option>
<option name="hamster-option" value="hamster">Hamster</option>
</select>
This triggers the validation error because name is not a valid attribute on <option>.
Correct: using id instead of name
If you need to uniquely identify each option (for example, to target them with JavaScript or CSS), use the id attribute:
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option id="dog-option" value="dog">Dog</option>
<option id="cat-option" value="cat">Cat</option>
<option id="hamster-option" value="hamster">Hamster</option>
</select>
Correct: simply removing name if no reference is needed
In most cases, you don’t need to identify individual options at all. The value attribute is sufficient for form submission, and you can remove name entirely:
<select id="pet-select" name="pet">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
<option value="hamster">Hamster</option>
</select>
Note that the name attribute on the <select> element itself is perfectly valid and necessary — it defines the key used when the form data is submitted. The obsolete attribute warning applies only to name on <option> elements.
The <label> element associates descriptive text with a specific form control, enabling users to click the label to focus or activate the associated input. The for attribute creates this link by referencing the id of the target form control. When the referenced id doesn’t correspond to a valid, non-hidden form control, the label becomes orphaned — it isn’t associated with anything meaningful.
The W3C validator raises this error in several scenarios:
- The for attribute references an id that doesn’t exist in the document.
- The for attribute references an element that isn’t a labelable element (such as a <div> or <span>).
- The for attribute references an <input type="hidden">, which is not a visible form control and cannot be labeled.
- There’s a typo or mismatch between the for value and the intended element’s id.
Labelable elements in HTML include <input> (except type="hidden"), <select>, <textarea>, <button>, <meter>, <output>, and <progress>.
This matters for accessibility because screen readers rely on the for/id association to announce what each form control represents. Without a valid association, users who depend on assistive technology may not understand what a form field is asking for. It also impacts usability — a properly linked label expands the clickable area for the form control, making it easier to interact with, especially on touch devices and for users with motor impairments.
To fix this issue, verify that the for attribute value exactly matches the id of a visible, labelable form control. If you’re labeling a hidden input, consider whether the label is necessary at all (hidden inputs are not user-facing). If the target element isn’t a form control, either change it to the appropriate form element or use a different approach like aria-labelledby.
Examples
❌ for references a non-existent ID
<label for="username">Username</label>
<input id="user-name" type="text">
The for value "username" doesn’t match the input’s id of "user-name".
✅ Fixed: matching for and id
<label for="username">Username</label>
<input id="username" type="text">
❌ for references a hidden input
<label for="token">Token</label>
<input id="token" type="hidden" value="abc123">
An <input type="hidden"> is not a visible form control and cannot be labeled.
✅ Fixed: remove the unnecessary label
<input id="token" type="hidden" value="abc123">
Hidden inputs don’t need labels since users never interact with them directly.
❌ for references a non-labelable element
<label for="info">Information</label>
<div id="info">Some details here</div>
A <div> is not a labelable element, so the for association is invalid.
✅ Fixed: use a proper form control or implicit labeling
<label for="info">Information</label>
<textarea id="info"></textarea>
❌ for references an element inside another form control
<label for="opt">Choose one</label>
<select>
<option id="opt" value="a">Option A</option>
</select>
An <option> element is not a labelable element. The label should point to the <select>.
✅ Fixed: reference the <select> element
<label for="choice">Choose one</label>
<select id="choice">
<option value="a">Option A</option>
</select>
Using implicit labeling as an alternative
Instead of using the for attribute, you can wrap the form control inside the <label> element. This creates an implicit association without needing for or id at all:
<label>
Age
<input type="number">
</label>
This approach avoids the for/id mismatch problem entirely and is equally valid for accessibility.
Ready to validate your sites?
Start your free trial today.