HTML Guides
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 requires that the width and height attributes on <img> elements, when present, contain a string representing a non-negative integer — that is, a sequence of one or more ASCII digits like "0", "150", or "1920". An empty string ("") does not satisfy this requirement, so the W3C validator flags it as an error.
This issue commonly arises when:
- A CMS or templating engine outputs
width=""orheight=""because no dimension value was configured. - JavaScript dynamically sets
img.setAttribute("width", "")instead of removing the attribute. - A developer adds the attributes as placeholders intending to fill them in later but forgets to do so.
Why it matters
Providing valid width and height attributes is one of the most effective ways to prevent Cumulative Layout Shift (CLS). Browsers use these values to calculate the image's aspect ratio and reserve the correct amount of space before the image loads. When the values are empty strings, the browser cannot determine the aspect ratio, so no space is reserved — leading to layout shifts as images load in, which hurts both user experience and Core Web Vitals scores.
Beyond performance, invalid attribute values can cause unpredictable rendering behavior across browsers. Some browsers may ignore the attribute, others may interpret the empty string as 0, collapsing the image to zero pixels in that dimension. Standards-compliant HTML also improves accessibility by ensuring assistive technologies can parse the document reliably.
Examples
❌ Invalid: empty string values
<imgsrc="photo.jpg"alt="A sunset over the ocean"width=""height="">
Both width and height are set to empty strings, which is not valid.
✅ Fixed: provide actual dimensions
<imgsrc="photo.jpg"alt="A sunset over the ocean"width="800"height="600">
Replace the empty strings with the image's actual pixel dimensions. These values should reflect the image's intrinsic (natural) size. CSS can still be used to scale the image visually — the browser will use the width and height ratio to reserve the correct space.
✅ Fixed: remove the attributes entirely
<imgsrc="photo.jpg"alt="A sunset over the ocean">
If you don't know the dimensions or prefer to handle sizing purely through CSS, remove the attributes altogether. An absent attribute is valid; an empty one is not.
❌ Invalid: only one attribute is empty
<imgsrc="banner.jpg"alt="Promotional banner"width="1200"height="">
Even if only one attribute has an empty value, the validation error will be triggered for that attribute.
✅ Fixed: both attributes with valid values
<imgsrc="banner.jpg"alt="Promotional banner"width="1200"height="400">
Fixing dynamic/template-generated markup
If a template language is outputting empty attributes, use a conditional to omit them when no value is available. For example, in a template:
<!-- Instead of always outputting the attributes: -->
<imgsrc="photo.jpg"alt="Description"width=""height="">
<!-- Conditionally include them only when values exist: -->
<imgsrc="photo.jpg"alt="Description"width="800"height="600">
If you're setting dimensions via JavaScript, remove the attribute rather than setting it to an empty string:
// ❌ Don't do this
img.setAttribute("width","");
// ✅ Do this instead
img.removeAttribute("width");
// ✅ Or set a valid value
img.setAttribute("width","800");
A note on values
The width and height attributes only accept non-negative integers — whole numbers without units, decimals, or percentage signs. Values like "100px", "50%", or "3.5" are also invalid. Use plain integers like "100" or "600". If you need responsive sizing with percentages or other CSS units, apply those through CSS styles instead.
The xmlns attribute declares the XML namespace for an element. For SVG elements, the only permitted namespace is "http://www.w3.org/2000/svg". When this attribute is present but set to an empty string ("") or any value other than the correct namespace, the W3C validator reports an error because the browser cannot properly associate the element with the SVG specification.
In HTML5 documents (served as text/html), the xmlns attribute on <svg> is actually optional. The HTML parser automatically associates <svg> elements with the correct SVG namespace without needing an explicit declaration. However, if you do include the xmlns attribute — for example, because your SVG was exported from a design tool or copied from an XML-based source — it must contain the exact value "http://www.w3.org/2000/svg". An empty or incorrect value will cause a validation error and could lead to rendering issues in certain contexts.
This matters for several reasons:
- Standards compliance: The HTML specification explicitly restricts the allowed value for
xmlnson SVG elements. - Browser compatibility: While most modern browsers are forgiving in HTML mode, an incorrect namespace can cause problems when SVG content is used in XML contexts (such as XHTML or standalone
.svgfiles). - Interoperability: Tools and libraries that process your HTML may rely on the correct namespace to identify and manipulate SVG elements.
To fix this issue, you have two options:
- Set the correct value: Replace the empty or incorrect
xmlnsvalue with"http://www.w3.org/2000/svg". - Remove the attribute entirely: Since
xmlnsis optional in HTML5, simply removing it is often the cleanest solution.
Examples
Incorrect: empty xmlns attribute
This triggers the validation error because the namespace value is an empty string:
<svgxmlns=""width="100"height="100">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Incorrect: wrong namespace value
Any value other than the correct SVG namespace will also trigger this error:
<svgxmlns="http://www.w3.org/2000/html"width="100"height="100">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Fix: use the correct namespace
Set xmlns to the only permitted value:
<svgxmlns="http://www.w3.org/2000/svg"width="100"height="100">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Fix: remove the xmlns attribute
In an HTML5 document, you can omit xmlns altogether since the parser handles the namespace automatically:
<svgwidth="100"height="100">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Note on inline SVG from external sources
Design tools like Figma, Illustrator, or Inkscape often export SVG files with the xmlns attribute already set correctly. If you're copying SVG markup and the xmlns value gets accidentally cleared or corrupted during the process, either restore it to "http://www.w3.org/2000/svg" or remove it before embedding the SVG in your HTML. Both approaches will produce valid, working markup.
The role="group" attribute is not allowed on the article element because article already has an implicit ARIA role of article, and group is not among the roles permitted on this element.
The article element represents a self-contained composition in a document, such as a blog post, a news story, or a forum comment. Its implicit ARIA role is article. According to the ARIA in HTML specification, the article element can only use a limited set of roles: application, document, feed, main, none, presentation, or region. The group role is not in that list.
If you need a group role, use a generic element like div or span instead. If you need the semantic meaning of article, keep the article element and remove the role="group" attribute.
Example with the issue
<articlerole="group">
<h2>Latest news</h2>
<p>Content of the article.</p>
</article>
How to fix it
If group semantics are what you need, switch to a div:
<divrole="group"aria-label="Latest news">
<h2>Latest news</h2>
<p>Content of the article.</p>
</div>
If article semantics are what you need, drop the conflicting role:
<article>
<h2>Latest news</h2>
<p>Content of the article.</p>
</article>
The W3C HTML specification restricts which ARIA roles can be used on specific elements. An li element already carries the implicit role of listitem when it's a child of a ul or ol, so adding an explicit role is often unnecessary. The group role, as defined in the WAI-ARIA specification, is meant for container elements that form a logical collection of related items — similar to how a fieldset groups form controls. Applying group to an li element contradicts the element's purpose as an individual item within a list.
This matters for several reasons. Assistive technologies like screen readers rely on ARIA roles to communicate the structure and purpose of content to users. When an li element is marked with role="group", it overrides the native listitem semantics, potentially confusing users who depend on these tools. A screen reader might announce the element as a group container rather than a list item, breaking the expected navigation pattern of the list. Browsers and assistive technologies are optimized around correct role usage, so invalid combinations can lead to unpredictable behavior.
When you might actually need group
If your intent is to group a set of related elements together, the group role belongs on a wrapping container — not on the individual items inside it. For example, you might use role="group" on a div or a ul that contains a subset of related controls within a larger interface. If an li contains nested interactive content that needs to be grouped, wrap that content in an inner container with the group role instead.
How to fix it
- Remove the role entirely if the
liis a standard list item inside aulorol. The browser already provides the correctlistitemsemantics. - Move the
grouprole to a container element if you genuinely need to create a labeled group of related items. - Use a different valid role if the
liserves a non-standard purpose, such asmenuitem,option,tab,treeitem, orpresentation, depending on the widget pattern you're building.
Examples
Incorrect: group role on li elements
<ul>
<lirole="group">Fruits</li>
<lirole="group">Vegetables</li>
<lirole="group">Grains</li>
</ul>
This triggers the validation error because group is not a permitted role for li.
Correct: no explicit role needed
<ul>
<li>Fruits</li>
<li>Vegetables</li>
<li>Grains</li>
</ul>
Each li inside a ul automatically has the listitem role. No additional markup is needed.
Correct: using group on a container element
If you need to group related items with a label, apply the group role to the container:
<divrole="group"aria-labelledby="food-heading">
<h2id="food-heading">Food Categories</h2>
<ul>
<li>Fruits</li>
<li>Vegetables</li>
<li>Grains</li>
</ul>
</div>
Correct: nested groups within list items
If each list item contains a group of related controls, place the group role on an inner wrapper:
<ul>
<li>
<divrole="group"aria-label="Text formatting">
<button>Bold</button>
<button>Italic</button>
<button>Underline</button>
</div>
</li>
<li>
<divrole="group"aria-label="Text alignment">
<button>Left</button>
<button>Center</button>
<button>Right</button>
</div>
</li>
</ul>
This preserves the list structure while correctly applying the group role to containers of related widgets. The aria-label attribute gives each group an accessible name, which is recommended when using role="group".
A space before the width attribute value is causing the validator to misparse the iframe attributes, likely due to a missing closing quote on the width attribute.
This error typically occurs when there's a typo in the attribute syntax, such as a missing closing quote or extra spaces inside the attribute value. The validator reads the raw HTML and interprets " height= as part of the width value because the width attribute's opening quote was never properly closed.
The width and height attributes on an iframe element accept non-negative integer values representing pixels. Each attribute must have its value properly quoted and contain only digits.
HTML Examples
❌ Incorrect
<iframesrc="page.html"width="600 height="400"></iframe>
In this example, the closing quote after 600 is missing. The validator sees the width value as 600 height=, which is not a valid number.
✅ Correct
<iframesrc="page.html"width="600"height="400"></iframe>
Each attribute has properly matched opening and closing quotes, and the values contain only digits.
The fetchpriority attribute is a hint to the browser about the relative priority of fetching a particular resource compared to other resources of the same type. It is defined in the WHATWG HTML living standard as an enumerated attribute with exactly three valid values:
high— The resource should be fetched at a higher priority relative to other resources of the same type.low— The resource should be fetched at a lower priority relative to other resources of the same type.auto— The browser determines the appropriate priority (this is the default behavior).
Values like "highest", "critical", "urgent", or any other string outside these three are not recognized. When the W3C validator encounters an invalid value, it reports: Bad value "highest" for attribute "fetchpriority" on element "link".
Why This Matters
Standards compliance: Browsers treat unrecognized fetchpriority values as equivalent to "auto", meaning your intended priority hint is silently ignored. If you wrote fetchpriority="highest" expecting it to be even more urgent than "high", that extra emphasis has no effect — the browser simply falls back to its default prioritization.
Developer intent: An invalid value masks your real intention. Another developer reading the code might assume "highest" does something special, when in reality the browser discards it. Using the correct value makes the code's purpose clear and ensures the hint is actually applied.
Accessibility and performance: The fetchpriority attribute is commonly used on <link rel="preload"> elements for critical resources like fonts, stylesheets, or hero images. If your priority hint is silently ignored due to an invalid value, key resources may not load as quickly as intended, potentially degrading the user experience.
How to Fix It
Replace the invalid value with one of the three accepted values. In most cases, if you used "highest", you likely meant "high":
- Find every
<link>element wherefetchpriorityhas an invalid value. - Change the value to
"high","low", or"auto". - If you're unsure which priority to use, omit the attribute entirely — the browser will use
"auto"by default.
Note that fetchpriority also works on <img>, <script>, and <iframe> elements, and the same three-value restriction applies to all of them.
Examples
Incorrect: Invalid fetchpriority value
<linkrel="preload"href="hero.webp"as="image"fetchpriority="highest">
The value "highest" is not valid. The browser ignores the hint and falls back to default prioritization.
Correct: Using "high" for elevated priority
<linkrel="preload"href="hero.webp"as="image"fetchpriority="high">
Correct: Using "low" for deferred resources
<linkrel="preload"href="analytics.js"as="script"fetchpriority="low">
Correct: Omitting the attribute for default behavior
<linkrel="preload"href="style.css"as="style">
When omitted, the browser uses its default priority logic, which is equivalent to fetchpriority="auto".
Full document example
<!DOCTYPE html>
<htmllang="en">
<head>
<title>Fetch Priority Example</title>
<linkrel="preload"href="hero.webp"as="image"fetchpriority="high">
<linkrel="preload"href="fonts/body.woff2"as="font"type="font/woff2"crossoriginfetchpriority="high">
<linkrel="stylesheet"href="style.css">
</head>
<body>
<imgsrc="hero.webp"alt="Hero banner"fetchpriority="high">
<p>Page content goes here.</p>
</body>
</html>
This example preloads a hero image and a font with fetchpriority="high", and also applies the hint to the <img> element itself — all using valid attribute values.
When you set href="http://", the browser and the W3C validator attempt to parse this as an absolute URL. According to the URL Standard, a URL with the http or https scheme must include a non-empty host component. The string http:// has the scheme but nothing after the ://, which makes the host empty and the URL invalid.
This issue typically arises when a URL is dynamically generated but the variable or value for the domain is missing, or when a developer uses http:// as a temporary placeholder during development and forgets to replace it.
Why this matters
- Broken navigation: Clicking a link with
href="http://"leads to unpredictable behavior. Some browsers may navigate to an error page, while others may interpret it differently. - Accessibility: Screen readers announce links to users, including their destinations. An invalid URL creates a confusing experience for assistive technology users who expect the link to go somewhere meaningful.
- Standards compliance: The HTML specification requires that
hrefvalues be valid URLs. An empty host violates the URL parsing rules, causing the W3C validator to flag it as an error. - SEO: Search engine crawlers may treat invalid URLs as errors, potentially affecting how your site is indexed.
Examples
❌ Invalid: empty host in URL
<ahref="http://">Visit our website</a>
This triggers the error because http:// has no host component.
❌ Invalid: same issue with HTTPS
<ahref="https://">Secure link</a>
The https scheme also requires a valid host, so this produces the same error.
✅ Fixed: provide a complete URL
<ahref="https://example.com">Visit our website</a>
✅ Fixed: use a fragment placeholder if the URL is unknown
If you need a placeholder link during development, use # instead of an incomplete URL:
<ahref="#">Visit our website</a>
✅ Fixed: use a relative URL when linking within the same site
<ahref="/about">About us</a>
Handling dynamic URLs
If the href value comes from a template or CMS, make sure the variable outputs a complete URL. For example, if a template produces an empty string, you might end up with:
<!-- If {{ site_url }} is empty, this becomes href="http://" -->
<ahref="http://{{ site_url }}">Home</a>
Ensure that the variable always resolves to a valid host, or add a fallback so the link is omitted or replaced with a safe default when the value is missing.
The xmlns attribute declares the XML namespace for the document. When present on the <html> element, the HTML specification requires its value to be exactly http://www.w3.org/1999/xhtml — no variations allowed. The URL http://www.w3.org/1999/html is not a recognized namespace and will be rejected by the validator. This error almost always comes from a typo: the "x" before "html" was accidentally omitted.
Why this matters
While most browsers will still render the page in HTML mode regardless of a malformed xmlns value, an incorrect namespace can cause real problems in certain contexts:
- XHTML processing: If the document is served with an XML content type (e.g.,
application/xhtml+xml), an invalid namespace will cause XML parsers to reject or misinterpret the document. - Standards compliance: Validators and automated tools flag this as an error, which can affect quality audits, accessibility checks, and CI/CD pipelines that enforce valid markup.
- Tooling and interoperability: XML-based tools, content management systems, and XSLT transformations rely on correct namespaces to function properly.
How to fix it
You have two options depending on your document type:
- If you need the
xmlnsattribute (e.g., for XHTML or polyglot documents): Change the value fromhttp://www.w3.org/1999/htmltohttp://www.w3.org/1999/xhtml. - If you're writing standard HTML5: Simply remove the
xmlnsattribute. It's optional in HTML5 and has no effect when present with the correct value — so omitting it is the cleanest approach.
Examples
Incorrect — misspelled namespace
The value is missing the "x" before "html":
<!DOCTYPE html>
<htmlxmlns="http://www.w3.org/1999/html"lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Fixed — correct XHTML namespace
Add the missing "x" so the value reads xhtml:
<!DOCTYPE html>
<htmlxmlns="http://www.w3.org/1999/xhtml"lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Fixed — standard HTML5 without xmlns
If you don't need XHTML compatibility, remove the attribute altogether:
<!DOCTYPE html>
<htmllang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
For most modern websites served as text/html, the third option — omitting xmlns entirely — is the simplest and recommended approach. Only include it if your document must also be valid XHTML or will be processed by XML tooling, and always ensure the value is exactly http://www.w3.org/1999/xhtml.
The xmlns attribute declares the XML namespace for a document. The value http://www.w3.org/TR/REC-html40 is a URL that points to the old HTML 4.0 Recommendation specification — it was never a proper XML namespace identifier. It likely ended up in code through confusion between DTD/specification URLs and actual namespace URIs, or by copying markup from outdated templates.
In the HTML5 specification (the WHATWG HTML Living Standard), the xmlns attribute on the <html> element is optional. When present, its value must be exactly http://www.w3.org/1999/xhtml — no other value is permitted. This is true regardless of whether the document is served as text/html or application/xhtml+xml.
Why this matters
- Validation failure: The W3C validator will reject the document because the namespace value is not one of the allowed values.
- Standards compliance: Using an incorrect namespace can cause XML parsers to misinterpret or reject the document, especially when served with an XML content type.
- Legacy confusion: The
http://www.w3.org/TR/REC-html40URL is a specification reference, not a namespace. Namespaces and specification URLs serve fundamentally different purposes in web standards.
How to fix it
The simplest fix for a standard HTML5 document is to remove the xmlns attribute entirely. The HTML parser does not require it, and browsers will process the document correctly without it.
If your document is served as XHTML (application/xhtml+xml), or if you have a specific reason to include the namespace declaration, update the value to the only permitted one: http://www.w3.org/1999/xhtml.
Examples
❌ Incorrect: old HTML 4.0 URL used as namespace
<!DOCTYPE html>
<htmlxmlns="http://www.w3.org/TR/REC-html40"lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
✅ Fix option 1: remove the xmlns attribute (recommended for HTML5)
For most HTML5 documents served as text/html, simply omit the attribute:
<!DOCTYPE html>
<htmllang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
✅ Fix option 2: use the correct namespace value
If you need the xmlns attribute (e.g., for XHTML serialization), set it to the only allowed value:
<!DOCTYPE html>
<htmlxmlns="http://www.w3.org/1999/xhtml"lang="en">
<head>
<title>My Page</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
Other incorrect values to watch for
This same error can appear with other invalid namespace URLs. All of the following are wrong:
http://www.w3.org/TR/REC-html40(HTML 4.0 spec URL)http://www.w3.org/TR/html4/(another HTML 4 spec URL)http://www.w3.org/1999/html(non-existent namespace)
The only valid value is http://www.w3.org/1999/xhtml. When in doubt, remove the xmlns attribute altogether — modern HTML5 documents don't need it.
Namespace URIs in XML (and by extension in HTML) are identifiers, not actual URLs that a browser fetches. The W3C and WHATWG specifications define http://www.w3.org/1998/Math/MathML as the one and only valid namespace for MathML. Even though http:// and https:// point to the same server in practice, they are different strings — and namespace matching is purely a string comparison. Using https://www.w3.org/1998/Math/MathML creates what the spec considers an entirely different (and unrecognized) namespace.
This is a common mistake because modern best practices encourage using https:// for everything on the web. However, these namespace URIs were standardized long before HTTPS became the norm, and changing them would break backward compatibility across the entire XML ecosystem. The spec is explicit: only http://www.w3.org/1998/Math/MathML is permitted.
How to Fix It
You have two options depending on your document type:
HTML5 (recommended): Simply remove the
xmlnsattribute from the<math>element. The HTML5 parser recognizes<math>and automatically places it in the correct MathML namespace. No explicit declaration is needed.XHTML or XML documents: If you're serving your document as
application/xhtml+xmlor working in an XML context where explicit namespaces are required, use the exact URIhttp://www.w3.org/1998/Math/MathMLwithhttp://.
The same rule applies to other well-known namespaces like SVG (http://www.w3.org/2000/svg) and XHTML (http://www.w3.org/1999/xhtml) — always use the http:// form specified in the standard.
Examples
Invalid: using https:// in the namespace URI
The https:// scheme causes the validation error:
<mathxmlns="https://www.w3.org/1998/Math/MathML">
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
Fixed: omit xmlns in HTML5
In an HTML5 document, the parser handles the namespace automatically, so the cleanest fix is to drop xmlns altogether:
<!DOCTYPE html>
<htmllang="en">
<head>
<title>MathML Example</title>
</head>
<body>
<math>
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
</body>
</html>
Fixed: use the correct http:// URI
If you need to explicitly declare the namespace (for example, in XHTML served as XML), use the exact http:// URI:
<mathxmlns="http://www.w3.org/1998/Math/MathML">
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
Quick comparison
| Code | Valid? |
|---|---|
<math xmlns="https://www.w3.org/1998/Math/MathML"> | ❌ Wrong scheme |
<math xmlns="http://www.w3.org/1998/Math/MathML"> | ✅ Correct URI |
<math> (in HTML5) | ✅ Namespace implied |
XML namespaces are identified by URI strings that act as unique names. They are never fetched or loaded by the browser — they simply serve as an identifier that must match exactly what the specification defines. The XLink namespace has been defined as http://www.w3.org/1999/xlink since its inception, and changing the protocol to https creates a completely different string that parsers and validators do not recognize.
It's a common and understandable mistake. Developers are trained to prefer https:// URLs everywhere for security, and many linting tools or habits may encourage automatically converting http:// to https://. However, namespace URIs are a special case where this rule does not apply. The string is purely declarative — no network request is made, and no security benefit comes from using https.
It's also worth noting that the xmlns:xlink attribute is largely obsolete in modern HTML. When SVG is embedded directly in an HTML5 document, browsers automatically handle namespace resolution. You only need xmlns:xlink when serving SVG as standalone XML (with an .svg file or application/xhtml+xml content type). In most cases, you can simply remove the attribute altogether and use xlink:href or, even better, the plain href attribute, which is now supported on SVG elements like <use>, <image>, and <a>.
Examples
Incorrect: using https:// in the namespace URI
<svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="https://www.w3.org/1999/xlink">
<usexlink:href="#icon-star"></use>
</svg>
This triggers the validation error because https://www.w3.org/1999/xlink does not match the required namespace identifier.
Fixed: using the correct http:// namespace URI
<svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink">
<usexlink:href="#icon-star"></use>
</svg>
Preferred: removing the namespace and using plain href
In HTML5, you can drop the xmlns:xlink declaration entirely and use the standard href attribute instead of xlink:href:
<svgxmlns="http://www.w3.org/2000/svg">
<usehref="#icon-star"></use>
</svg>
This is the cleanest approach for inline SVG in modern HTML documents. The xlink:href attribute is deprecated in SVG 2, and all modern browsers support plain href on SVG linking elements.
An XML namespace URI is a unique identifier, not an actual web address that your browser fetches. The SVG namespace was defined as http://www.w3.org/2000/svg in the original SVG specification, and that exact string is what HTML parsers and validators expect. Even though using https everywhere is a best practice for real network requests, namespace URIs are not network requests — they are simply fixed strings used to identify which XML vocabulary an element belongs to.
When you write https://www.w3.org/2000/svg instead of http://www.w3.org/2000/svg, the validator sees an unrecognized namespace. This can also cause problems in certain XML-based contexts (such as XHTML or standalone SVG files), where the browser may fail to recognize the element as SVG at all, resulting in your graphics not rendering. In standard HTML5 mode, most browsers will still render inline SVGs correctly regardless of the xmlns value, but the markup is technically invalid and may cause issues in stricter parsing environments like XML serializers, server-side renderers, or tools that process SVG as XML.
This mistake is especially common because many developers reflexively change http to https — or their editor or linter automatically does — when they see a URL-like string. The same principle applies to other namespace URIs like http://www.w3.org/1999/xhtml for HTML and http://www.w3.org/1998/Math/MathML for MathML. These are all fixed identifiers that must not be altered.
How to Fix It
Replace https:// with http:// in the xmlns attribute value. That's it — no other changes are needed.
If your project uses automated tooling that rewrites http URLs to https, you may need to configure an exception for XML namespace URIs.
Examples
❌ Incorrect: Using https in the namespace URI
<svgxmlns="https://www.w3.org/2000/svg"viewBox="0 0 100 100">
<circlecx="50"cy="50"r="40"fill="blue"/>
</svg>
This triggers the validation error because https://www.w3.org/2000/svg is not a recognized namespace value.
✅ Correct: Using http in the namespace URI
<svgxmlns="http://www.w3.org/2000/svg"viewBox="0 0 100 100">
<circlecx="50"cy="50"r="40"fill="blue"/>
</svg>
✅ Correct: Inline SVG in HTML without xmlns
When embedding SVG directly inside an HTML5 document, the xmlns attribute is optional — the HTML parser automatically assigns the correct namespace to <svg> elements:
<svgviewBox="0 0 100 100">
<circlecx="50"cy="50"r="40"fill="blue"/>
</svg>
This is perfectly valid HTML5. You only need the xmlns attribute when the SVG is served as a standalone .svg file or used within an XHTML document.
The WAI-ARIA specification defines a specific set of role values that assistive technologies like screen readers understand. These include roles such as button, checkbox, alert, dialog, img, navigation, banner, and many others. The value "icon" is not among them. When a browser or assistive technology encounters an unrecognized role, it cannot determine the element's purpose, which defeats the goal of using ARIA in the first place.
This is primarily an accessibility problem. Screen readers rely on valid ARIA roles to communicate the nature of elements to users. An invalid role like "icon" is either ignored or causes unpredictable behavior, leaving users of assistive technologies without the context they need. It's also a standards compliance issue — the W3C validator flags this because the HTML specification requires role values to match roles defined in the ARIA specification.
The fix depends on the purpose of the element:
- Decorative icons (that don't convey information): Remove the
roleattribute entirely, or usearia-hidden="true"to explicitly hide the element from the accessibility tree. - Meaningful icons (that convey information visually): Use
role="img"along with anaria-labelto provide a text alternative. - Icons inside interactive elements: Hide the icon with
aria-hidden="true"and ensure the parent interactive element has an accessible name through visible text or anaria-label.
Examples
❌ Invalid: Using the non-existent "icon" role
<spanclass="icon"role="icon"></span>
This triggers the validation error because "icon" is not a valid ARIA role.
✅ Fixed: Decorative icon with no role
If the icon is purely decorative and doesn't convey any meaning (e.g., it's next to text that already describes the action), simply remove the role attribute. Adding aria-hidden="true" ensures screen readers skip over it completely.
<spanclass="icon"aria-hidden="true"></span>
✅ Fixed: Meaningful icon using role="img"
If the icon conveys meaningful information that isn't available through surrounding text, use role="img" and provide a descriptive aria-label:
<spanclass="icon-warning"role="img"aria-label="Warning"></span>
This tells assistive technologies that the element represents an image and gives it an accessible name of "Warning."
✅ Fixed: Icon inside a button
When an icon is placed inside an interactive element like a button, hide the icon from the accessibility tree and let the button's text or label provide the meaning:
<button>
<spanclass="icon-save"aria-hidden="true"></span>
Save
</button>
If the button has no visible text (an icon-only button), provide an aria-label on the button itself:
<buttonaria-label="Save">
<spanclass="icon-save"aria-hidden="true"></span>
</button>
✅ Fixed: Icon using an <img> element instead
If you're using an actual image file for the icon, consider using a semantic <img> element, which has a built-in img role:
<imgsrc="icon-alert.svg"alt="Alert"class="icon">
For decorative image icons, use an empty alt attribute:
<imgsrc="icon-decorative.svg"alt=""class="icon">
The type attribute on a <link> element must contain a single MIME type, not a comma-separated list of multiple types.
The type attribute specifies the MIME type of the linked resource and only accepts one value. It helps the browser decide whether it can handle the resource before downloading it. If you want to reference a favicon that could be in PNG or ICO format, you should pick the single correct MIME type that matches the actual file you're linking to.
For .png favicons, use image/png. For .ico favicons, use image/x-icon. If you need to support both formats, use separate <link> elements — one for each file.
Invalid Example
<linkrel="icon"type="image/png, image/x-icon"href="/favicon.png">
Valid Examples
If your favicon is a PNG file:
<linkrel="icon"type="image/png"href="/favicon.png">
If you want to provide both formats, use two separate <link> elements:
<linkrel="icon"type="image/png"href="/favicon.png">
<linkrel="icon"type="image/x-icon"href="/favicon.ico">
The browser will select the most appropriate icon from the available options. Most modern browsers prefer PNG, while older browsers will fall back to ICO.
The display attribute on an <svg> element does not accept CSS values like inline-block. The display attribute in SVG is a presentation attribute that only accepts SVG-specific values: inline, block, list-item, none, and a few others defined in the SVG specification, but not inline-block.
SVG presentation attributes map to a limited subset of CSS properties, and their allowed values don't always match the full range of CSS values. The display presentation attribute on SVG elements accepts values like inline, block, none, run-in, table, and related table display values, but inline-block is not among them.
To apply inline-block display behavior to an <svg> element, use a style attribute or a CSS rule instead of the display presentation attribute.
Invalid example
<svgdisplay="inline-block"width="100"height="100"xmlns="http://www.w3.org/2000/svg">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Valid example
Use the style attribute to set inline-block:
<svgstyle="display:inline-block"width="100"height="100"xmlns="http://www.w3.org/2000/svg">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
Or apply it through CSS:
<style>
.icon{
display: inline-block;
}
</style>
<svgclass="icon"width="100"height="100"xmlns="http://www.w3.org/2000/svg">
<circlecx="50"cy="50"r="40"fill="red"/>
</svg>
The section element carries implicit ARIA semantics — it maps to role="region" when given an accessible name. According to the ARIA in HTML specification, each HTML element has a set of roles it is allowed to assume, and list is not among the permitted roles for section. When the W3C validator encounters role="list" on a section, it flags this as a bad value because the role conflicts with the element's intended purpose as a sectioning landmark.
This matters for several reasons. First, assistive technologies like screen readers rely on the correct pairing of elements and roles to convey page structure. A section announced as a list creates a confusing, contradictory experience — the underlying DOM says "this is a document section" while the ARIA role says "this is a list." Second, browsers may handle conflicting semantics unpredictably, leading to inconsistent behavior across platforms. Third, the HTML specification explicitly defines which roles are valid on each element, and violating these rules means your markup is non-conforming.
The best fix is almost always to use native HTML list elements. The ul, ol, and li elements provide built-in list semantics that all browsers and assistive technologies understand without any extra ARIA attributes. Native elements also handle keyboard interaction and focus management correctly out of the box.
If your design requires a custom component where native list markup isn't feasible — for example, a complex card grid that functions as a list — you can apply role="list" to a semantically neutral element like div or span. Each direct child acting as a list item should then receive role="listitem". This approach satisfies the ARIA specification while avoiding the element-role conflict.
If you actually need a section to group content within a page region and the list is just part of that section, nest a proper list inside the section rather than trying to make the section itself behave as a list.
Examples
❌ Bad: role="list" on a section element
This triggers the validation error because list is not an allowed role for section.
<sectionrole="list">
<div>Item A</div>
<div>Item B</div>
</section>
✅ Fixed: Use native list elements (recommended)
Native lists provide the best accessibility support with no ARIA needed.
<ul>
<li>Item A</li>
<li>Item B</li>
</ul>
✅ Fixed: Nest a list inside the section
If you need the sectioning semantics of section alongside a list, nest the list inside it.
<sectionaria-labelledby="resources-heading">
<h2id="resources-heading">Resources</h2>
<ul>
<li>Item A</li>
<li>Item B</li>
</ul>
</section>
✅ Fixed: ARIA roles on a neutral container
Use this only when native list markup is not possible, such as for highly custom UI components.
<divrole="list">
<divrole="listitem">Item A</div>
<divrole="listitem">Item B</div>
</div>
✅ Fixed: Remove the role entirely
If the content isn't actually a list, simply remove the role attribute and let the section carry its natural semantics.
<section>
<h2>Updates</h2>
<div>Item A</div>
<div>Item B</div>
</section>
The article element is a sectioning content element that represents a self-contained composition — a blog post, a news story, a forum entry, or similar independent content. Because it carries the implicit ARIA role of article, it functions as a landmark that assistive technologies recognize and expose to users for navigation. Overriding this landmark role with listitem creates a conflict: the element loses its article semantics for assistive technology users, and the listitem role itself becomes invalid because ARIA's role mapping rules don't permit it on article.
According to the ARIA in HTML specification, each HTML element has a set of allowed ARIA roles. The article element only permits a narrow set of roles (such as application, document, feed, main, none, presentation, and region). The listitem role is not among them. This restriction exists to prevent authors from creating confusing or contradictory semantics that would degrade the accessibility experience.
Beyond validation, this matters for real users. Screen readers rely on role information to convey structure. An article announced as a listitem is misleading — the user loses the ability to navigate by article landmarks, and the listitem may not function correctly without a proper parent list context. Browsers and assistive technologies expect listitem roles to appear as direct children of an element with role="list" (or within native ul/ol elements).
How to fix it
The solution depends on your intent:
- If you want a list of articles, use native HTML list markup (
ulorolwithli) and place eacharticleinside a list item. This gives you both list semantics and article landmarks without any ARIA overrides. - If you can't use native list elements, use neutral
divelements withrole="list"androle="listitem", and nest thearticleinside eachlistitemcontainer. - If the content isn't truly a list, simply remove the
role="listitem"attribute and let thearticleelement use its native semantics.
Examples
Invalid: role="listitem" on an article element
This triggers the validator error because listitem is not an allowed role for article.
<articlerole="listitem">
<h2>News item</h2>
<p>Details about this story.</p>
</article>
Valid: native list with article elements inside
Using ul and li provides proper list semantics while preserving the article landmark role.
<ul>
<li>
<article>
<h2>News item</h2>
<p>Details about this story.</p>
</article>
</li>
<li>
<article>
<h2>Another item</h2>
<p>More details here.</p>
</article>
</li>
</ul>
Valid: ARIA list roles on neutral containers with nested article elements
When native list elements aren't suitable for your layout, use div elements for the list structure and nest each article inside.
<divrole="list">
<divrole="listitem">
<article>
<h2>News item</h2>
<p>Details about this story.</p>
</article>
</div>
<divrole="listitem">
<article>
<h2>Another item</h2>
<p>More details here.</p>
</article>
</div>
</div>
Valid: standalone article without a list role
If the content doesn't belong in a list, simply remove the invalid role.
<article>
<h2>News item</h2>
<p>Details about this story.</p>
</article>
In every case, the key principle is the same: let the article element keep its native semantics, and use the appropriate list structure around it rather than forcing a conflicting role onto it.
A < character inside an href attribute is not valid in a URL and must be removed or percent-encoded.
The mailto: URL scheme expects a well formed email address directly after the colon, such as mailto:user@example.com. The angle brackets (< and >) sometimes seen around email addresses in mail headers or plain text are not part of the URL syntax. Including them in the href value produces an illegal character error because < and > are not permitted in URIs without percent-encoding.
If angle brackets appear in your markup, they likely got there by copying an address from an email header like From: User <user@example.com> and pasting the whole thing into the link. Strip the brackets so only the bare address remains.
HTML examples
Incorrect
<ahref="mailto:<user@example.com>">Email us</a>
Correct
<ahref="mailto:user@example.com">Email us</a>
A mailto: link follows URI syntax as defined by RFC 3986, which does not permit raw space characters anywhere in the URI. When the W3C validator encounters a space inside the href value of a mailto: link, it reports it as an illegal character in the scheme data. This most commonly happens due to a typo in the email address itself — for example, accidentally inserting a space in the domain name (example .com) or the local part (user name@example.com). It can also occur when query parameters like subject or body contain unencoded spaces.
This matters for several reasons. First, browsers may truncate or misinterpret the href at the space boundary, meaning the mail client may open with an incorrect or incomplete email address. Second, assistive technologies rely on well-formed URIs to communicate link destinations to users. A malformed mailto: link can confuse screen readers or prevent users from understanding where the link leads. Third, invalid markup signals poor quality to search engines and automated tools.
To fix this issue:
- Check the email address for typos. Remove any accidental spaces in the local part (before
@) or the domain part (after@). - Percent-encode spaces in query parameters. If you're using
subject,body, orccparameters in themailto:URI, replace spaces with%20. - Avoid copying and pasting email addresses from formatted documents, which can introduce non-breaking spaces or other invisible whitespace characters.
Examples
Invalid — space in the email address
A space in the domain name makes the URI invalid:
<ahref="mailto:user@example com">Send Email</a>
Valid — corrected email address
Remove the space to form a valid email address:
<ahref="mailto:user@example.com">Send Email</a>
Invalid — space in the local part
<ahref="mailto:john doe@example.com">Send Email</a>
Valid — space removed from local part
<ahref="mailto:johndoe@example.com">Send Email</a>
Invalid — unencoded spaces in subject parameter
<ahref="mailto:info@example.com?subject=Hello World">Email Us</a>
Valid — percent-encoded spaces in subject parameter
Replace each space with %20 in query parameter values:
<ahref="mailto:info@example.com?subject=Hello%20World">Email Us</a>
Valid — full mailto with multiple parameters
<ahref="mailto:support@example.com?subject=Bug%20Report&body=Please%20describe%20the%20issue.">
Report a Bug
</a>
In HTML, every element has a set of ARIA roles it is allowed to carry. The ul element implicitly has the list role, and the ARIA specification only permits certain roles to override it — specifically directory, group, listbox, menu, menubar, none, presentation, radiogroup, tablist, toolbar, and tree. The navigation role is not among them.
The navigation role is a landmark role, meaning it identifies a major section of the page dedicated to navigational links. HTML5 introduced the nav element specifically for this purpose, and it carries the navigation role implicitly — no role attribute needed. When you place role="navigation" on a ul, you're conflicting with the element's semantics. A ul represents a list of items, not a navigational landmark. Assistive technologies like screen readers rely on correct role assignments to help users understand page structure and navigate efficiently. An incorrect role can confuse users by misrepresenting what the element actually is.
Beyond accessibility concerns, this is a standards compliance issue. The W3C validator enforces the rules defined in the ARIA in HTML specification, which maps each HTML element to its allowed roles. Violating these rules means your markup is invalid and may behave unpredictably across different browsers and assistive technologies.
The fix is straightforward: use a nav element as the wrapper for your navigation list. This gives you the navigation landmark semantics automatically, while the ul retains its proper list role. Both elements work together — the nav tells assistive technologies "this is a navigation section," and the ul tells them "here is a list of links."
Examples
❌ Incorrect: navigation role on a ul
This triggers the validation error because navigation is not an allowed role for ul.
<ulrole="navigation">
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
✅ Correct: wrapping the ul in a nav element
The nav element provides the navigation landmark implicitly. No role attribute is needed.
<nav>
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
</nav>
✅ Correct: labeling multiple navigation landmarks
When a page has more than one nav element, use aria-label to distinguish them for screen reader users.
<navaria-label="Main">
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
</nav>
<navaria-label="Footer">
<ul>
<li><ahref="/privacy">Privacy Policy</a></li>
<li><ahref="/terms">Terms of Service</a></li>
</ul>
</nav>
✅ Correct: using an allowed role on ul
If you need the ul to behave as something other than a plain list — for example, a menu in a web application — use one of its permitted roles.
<ulrole="menubar">
<lirole="menuitem"><ahref="/">Home</a></li>
<lirole="menuitem"><ahref="/about">About</a></li>
<lirole="menuitem"><ahref="/contact">Contact</a></li>
</ul>
Note that menu and menubar roles are meant for application-style menus with keyboard interaction, not for simple site navigation. For standard website navigation, the nav wrapper approach is almost always the right choice.
The autocomplete="new-password" value can only be used on <input> elements whose type accepts password input, specifically type="password".
The autocomplete attribute helps browsers autofill form fields. However, certain autofill tokens are restricted to specific input types. The new-password token tells the browser to suggest a new, generated password — which only makes sense on a password field. If you use it on a type="text", type="email", or other non-password input, the validator will flag it as invalid.
The same restriction applies to current-password. Both tokens are exclusively valid on <input type="password">.
Invalid Example
<labelfor="pass">Create a password</label>
<inputtype="text"id="pass"autocomplete="new-password">
Valid Example
<labelfor="pass">Create a password</label>
<inputtype="password"id="pass"autocomplete="new-password">
If your field is not meant to collect a password, use a different autocomplete value appropriate for the input type, such as username, email, or off.
The autocomplete attribute tells the browser how to handle autofilling a form field. The HTML specification defines a strict set of allowed values: the keywords on and off, and a collection of autofill field names such as name, email, username, new-password, street-address, and many others. The value "none" is not part of this specification, even though it might seem like a logical choice for "no autocomplete."
This confusion likely arises because some non-web APIs and frameworks use "none" as a keyword to disable features. In HTML, however, the correct keyword to disable autocompletion is "off". Using an invalid value like "none" leads to undefined browser behavior — some browsers may ignore it entirely and autofill anyway, while others might treat it as equivalent to "on". This inconsistency can cause unexpected user experiences and potential security concerns, especially for sensitive fields like passwords or credit card numbers.
Beyond standards compliance, using valid autocomplete values improves accessibility. Assistive technologies and password managers rely on recognized autofill field names to help users fill out forms efficiently. When a valid, descriptive value like "username" or "email" is provided, browsers and assistive tools can offer more accurate suggestions.
How to fix it
Replace "none" with the appropriate valid value:
- Use
"off"if you want to disable autofill for the field. - Use
"on"if you want the browser to decide how to autofill the field. - Use a specific autofill field name if you want to hint at the type of data expected.
Common autofill field names include: name, given-name, family-name, email, username, new-password, current-password, tel, street-address, postal-code, country, cc-number, cc-exp, and cc-name. You can also combine tokens, such as "shipping postal-code" or "billing cc-number", to provide additional context through section and hint tokens.
Note: Even with
autocomplete="off", some browsers may still autofill certain fields (particularly login credentials) for security or usability reasons. This is browser-specific behavior and not something the HTML specification can override.
Examples
Incorrect: using "none" to disable autofill
<form>
<labelfor="user">Username</label>
<inputtype="text"id="user"name="username"autocomplete="none">
</form>
Correct: using "off" to disable autofill
<form>
<labelfor="user">Username</label>
<inputtype="text"id="user"name="username"autocomplete="off">
</form>
Correct: using a specific autofill field name
When you know what kind of data a field collects, providing a descriptive autofill field name is often better than using "on" or "off". This helps browsers offer accurate suggestions:
<form>
<labelfor="user">Username</label>
<inputtype="text"id="user"name="username"autocomplete="username">
<labelfor="email">Email</label>
<inputtype="email"id="email"name="email"autocomplete="email">
<labelfor="pwd">New Password</label>
<inputtype="password"id="pwd"name="password"autocomplete="new-password">
</form>
Correct: using section and hint tokens
You can prefix an autofill field name with a section name or shipping/billing hint to distinguish between multiple addresses in the same form:
<form>
<labelfor="ship-zip">Shipping postal code</label>
<inputtype="text"id="ship-zip"name="ship_zip"autocomplete="shipping postal-code">
<labelfor="bill-zip">Billing postal code</label>
<inputtype="text"id="bill-zip"name="bill_zip"autocomplete="billing postal-code">
</form>
The autocorrect attribute on <input> elements does not accept "none" as a valid value. The correct value to disable autocorrection is "off".
The autocorrect attribute controls whether the browser should automatically correct text input. It accepts only two values: "on" to enable autocorrection and "off" to disable it. The value "none" is not part of the specification and will fail W3C validation.
This attribute was originally a non-standard Safari extension, but it has since been added to the HTML standard. It applies to <input> elements that accept text input (such as text, search, and url types), <textarea> elements, and elements with contenteditable set.
Note that autocorrect is different from autocomplete, which uses "off" and "on" as well, but also accepts many other token values like "name" or "email". The two attributes control different behaviors: autocorrect handles spelling correction, while autocomplete handles previously entered values and autofill.
Incorrect example
<inputtype="text"autocorrect="none">
Correct example
<inputtype="text"autocorrect="off">
The SVG font-weight presentation attribute controls the boldness or lightness of glyphs used to render text. According to the SVG specification, this attribute is only valid on text content elements: <text>, <tspan>, <textPath>, and the deprecated <tref>. While the <g> element is a general-purpose container for grouping SVG elements, it does not accept font-weight as a direct attribute in valid markup.
The value "none" compounds the problem because it is not a recognized value for font-weight in any context. The allowed values are:
normal(equivalent to400)bold(equivalent to700)bolder(relative to parent)lighter(relative to parent)- A numeric value:
100,200,300,400,500,600,700,800, or900
This matters for standards compliance and predictable rendering across browsers. While some browsers may silently ignore invalid attributes or values, relying on that behavior leads to fragile code. Using valid attributes on the correct elements ensures consistent results and avoids validation errors.
If you need to apply a font-weight to multiple text elements inside a <g>, use CSS instead. You can apply a style via the style attribute on the <g>, a class, or an inline <style> block. CSS font-weight is inherited, so child text elements will pick it up.
Examples
Invalid: font-weight="none" on a <g> element
<svgviewBox="0 0 200 30"xmlns="http://www.w3.org/2000/svg">
<gfont-weight="none">
<texty="20">Hello</text>
</g>
</svg>
This triggers the validation error because <g> does not accept the font-weight attribute directly, and "none" is not a valid value.
Fixed: font-weight on the <text> element with a valid value
<svgviewBox="0 0 200 30"xmlns="http://www.w3.org/2000/svg">
<g>
<texty="20"font-weight="bold">Hello</text>
</g>
</svg>
Fixed: using a numeric weight on <text>
<svgviewBox="0 0 200 30"xmlns="http://www.w3.org/2000/svg">
<texty="20"font-weight="700">Bold text</text>
<textx="100"y="20"font-weight="400">Normal text</text>
</svg>
Fixed: applying font-weight to a <g> via CSS
If you want all text inside a <g> to share the same weight, use the style attribute or a CSS class. CSS-based font-weight on a <g> is valid because CSS inheritance applies to all descendant text content.
<svgviewBox="0 0 300 30"xmlns="http://www.w3.org/2000/svg">
<gstyle="font-weight:bold">
<texty="20">This is bold</text>
<textx="150"y="20">Also bold</text>
</g>
</svg>
Fixed: using an inline <style> block
<svgviewBox="0 0 300 30"xmlns="http://www.w3.org/2000/svg">
<style>
.heavy{font-weight:900;}
</style>
<gclass="heavy">
<texty="20">Heavy text</text>
<textx="150"y="20">Also heavy</text>
</g>
</svg>
This W3C validation error has two distinct problems combined into one message. First, the value "none" is not a recognized value for the text-anchor attribute — the only accepted values are start, middle, and end. Second, the <g> element is a generic container used to group SVG shapes together and does not support the text-anchor attribute directly.
The text-anchor attribute controls how text is aligned relative to its anchor point (the x coordinate). A value of start aligns the beginning of the text to the anchor, middle centers the text on the anchor, and end aligns the end of the text to the anchor. There is no "none" value because text always needs an alignment — start is the default if the attribute is omitted.
Why this is a problem
- Invalid markup: Using an unrecognized value like
"none"means browsers must guess the intended behavior, which can lead to inconsistent rendering across different environments. - Wrong element: The
<g>element does not directly render text, sotext-anchorhas no meaningful effect on it. While CSS inheritance might cause child text elements to pick up styles from a parent<g>, thetext-anchorpresentation attribute is only valid on elements that actually render text content. - Standards compliance: The SVG specification explicitly defines which elements accept
text-anchorand which values are allowed. Violating this produces validation errors and may cause issues with SVG processing tools.
How to fix it
- Remove the attribute from the
<g>element and apply it to the appropriate text element inside the group. - Replace
"none"with a valid value:start,middle, orend. If you want the default behavior (left-aligned for LTR text), simply omit the attribute entirely, asstartis the default. - If you need to set
text-anchorfor multiple text elements inside a group, use CSS instead of the presentation attribute.
Examples
❌ Invalid: "none" on a <g> element
<svgwidth="200"height="200">
<gtext-anchor="none">
<textx="100"y="100">Hello</text>
</g>
</svg>
✅ Fixed: valid value on the <text> element
<svgwidth="200"height="200">
<textx="100"y="100"text-anchor="middle">Hello</text>
</svg>
✅ Fixed: attribute removed entirely (uses default start)
<svgwidth="200"height="200">
<g>
<textx="100"y="100">Hello</text>
</g>
</svg>
✅ Using CSS to style text inside a group
If you want all text elements within a group to share the same alignment, apply the style via CSS rather than a presentation attribute on <g>:
<svgwidth="200"height="200">
<style>
.centered-texttext{
text-anchor: middle;
}
</style>
<gclass="centered-text">
<textx="100"y="50">First line</text>
<textx="100"y="100">Second line</text>
</g>
</svg>
✅ Valid use on other text-related elements
The text-anchor attribute can also be applied to <tspan> and <textPath>:
<svgwidth="300"height="100">
<textx="150"y="50"text-anchor="start">
Start-aligned
<tspanx="150"dy="30"text-anchor="end">End-aligned span</tspan>
</text>
</svg>
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.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries