HTML Guides for attribute
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.
When the HTML parser encounters a < character inside an opening tag, it doesn't treat it as the start of a new tag — instead, it tries to interpret it as an attribute name. Since < is not a valid attribute name, the W3C validator raises this error. The browser may still render the page, but the behavior is undefined and can vary across different browsers, potentially leading to broken markup or elements that don't display correctly.
This issue most commonly occurs in a few scenarios:
- Accidental keystrokes — a stray
<typed while editing attributes. - Copy-paste artifacts — fragments of other tags getting pasted into the middle of an element.
- Misplaced angle brackets — attempting to nest or close tags incorrectly, such as adding
<before/>in a self-closing tag. - Template or code generation errors — dynamic HTML output that incorrectly injects
<into attribute positions.
Because this is a syntax-level problem, it can cause cascading parse errors. The parser may misinterpret everything after the stray < until it finds a matching >, which can swallow subsequent elements or attributes and produce unexpected rendering results.
How to Fix It
- Open the file referenced by the validator error and go to the indicated line number.
- Look inside the opening tag of the flagged element for a
<character that doesn't belong. - Remove the stray
<character. - If the
<was meant to represent a literal less-than sign in an attribute value, replace it with the HTML entity<.
Examples
Stray < before the closing slash
<!-- ❌ Stray "<" before the self-closing slash -->
<img src="photo.jpg" alt="smiling cat" < />
<!-- ✅ Fixed: removed the stray "<" -->
<img src="photo.jpg" alt="smiling cat" />
Stray < between attributes
<!-- ❌ Accidental "<" between attributes -->
<a href="/about" < class="nav-link">About</a>
<!-- ✅ Fixed: removed the stray "<" -->
<a href="/about" class="nav-link">About</a>
Fragment of another tag pasted inside an element
<!-- ❌ Leftover "<span" pasted inside the div's opening tag -->
<div class="card" <span>
<p>Hello world</p>
</div>
<!-- ✅ Fixed: removed the pasted fragment -->
<div class="card">
<p>Hello world</p>
</div>
Literal < intended in an attribute value
If you actually need a less-than sign inside an attribute value — for example, in a title or data-* attribute — use the < entity instead of a raw <.
<!-- ❌ Raw "<" in an attribute value can cause parsing issues -->
<span title="x < 10">Threshold</span>
<!-- ✅ Fixed: use the HTML entity -->
<span title="x < 10">Threshold</span>
The src attribute appears as a bare name, with no = and no value, which leaves the element with an empty URL.
HTML lets you drop the value only on boolean attributes such as disabled, hidden or async, where having the attribute at all is what counts. src holds the address of the image, script, frame or media file to load, so it needs one. The parser reads <img src> as <img src="">, and the validator pairs this warning with an error on the same element saying the src value must be non-empty. The IE7 note comes from a time when that browser could drop attributes written this way. IE7 is long gone, but the empty URL still breaks the element.
A browser has nothing to fetch for an empty src. An <img> loads no image and fires its error event, and a <script> fires error without running. The bare src often comes from a lazy-loading script that keeps the real address in data-src until the image scrolls into view, or from a template whose image variable printed nothing.
Put the real URL in src. The native loading="lazy" attribute defers the download without any script. If there's no image to show, leave the <img> out of the page instead of printing it with an empty src.
Invalid example
<img src alt="Our team" data-src="/images/team.jpg" class="lazyload">
Valid example
<img src="/images/team.jpg" alt="Our team" loading="lazy">
When graphic design tools like Affinity Designer (formerly Serif) export SVG files, they often embed custom namespace declarations such as xmlns:serif="http://www.serif.com/". These namespaces allow the editor to store its own metadata — like layer names, grouping information, or application-specific settings — inside the SVG file. While this metadata is useful if you re-open the file in the original editor, it has no meaning in a web browser.
The HTML5 specification defines a specific set of namespace attributes that are allowed in SVG elements (such as xmlns, xmlns:xlink, and xmlns:xml). Any namespace prefix not in this predefined list — like xmlns:serif, xmlns:inkscape, or xmlns:sodipodi — triggers this validation error because the HTML parser cannot serialize these attributes back into well-formed XML 1.0. This isn't just a theoretical concern: non-serializable attributes can cause issues when the DOM is manipulated via JavaScript or when the markup is processed by XML-based tools.
Beyond the xmlns:serif declaration itself, you'll likely find attributes in the SVG that use this namespace prefix, such as serif:id="layer1". These should also be removed since they reference a namespace the browser doesn't understand.
How to Fix It
- Remove the
xmlns:serifattribute from the<svg>element. - Remove any attributes prefixed with
serif:(e.g.,serif:id) from child elements within the SVG. - If you re-export the SVG, check your editor's export settings — some tools offer a "clean" or "optimized" export option that strips proprietary metadata.
- Consider using an SVG optimization tool like SVGO to automatically clean up unnecessary attributes.
Examples
❌ Invalid: SVG with xmlns:serif attribute
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"
viewBox="0 0 100 100"
width="100"
height="100">
<g serif:id="Layer 1">
<circle cx="50" cy="50" r="40" fill="blue" />
</g>
</svg>
This triggers the error because xmlns:serif is not a recognized namespace in HTML5, and serif:id references that unsupported namespace.
✅ Valid: SVG with proprietary attributes removed
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
width="100"
height="100">
<g>
<circle cx="50" cy="50" r="40" fill="blue" />
</g>
</svg>
Both xmlns:serif and serif:id have been removed. The SVG renders identically in the browser since those attributes were only meaningful to the editing application.
Handling Multiple Proprietary Namespaces
Exported SVGs sometimes contain several non-standard namespaces at once. Remove all of them:
<!-- ❌ Invalid: multiple proprietary namespaces -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:serif="http://www.serif.com/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 200 200">
<rect x="10" y="10" width="180" height="180" fill="red"
serif:id="background"
inkscape:label="bg-rect" />
</svg>
<!-- ✅ Valid: all proprietary namespaces and prefixed attributes removed -->
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200">
<rect x="10" y="10" width="180" height="180" fill="red" />
</svg>
If you frequently work with SVGs from design tools, integrating an SVG optimizer into your build process can save time and ensure these non-standard attributes never reach production.
When the W3C HTML Validator reports that an attribute is "not serializable as XML 1.0," it means the attribute name contains characters that fall outside the allowed range defined by the XML 1.0 specification. HTML5 documents can be serialized as either HTML or XML (XHTML), and the validator checks that your markup is compatible with both serialization formats. Attribute names in XML 1.0 must start with a letter or underscore and can only contain letters, digits, hyphens, underscores, periods, and certain Unicode characters — they cannot include characters like {, }, @, $, or other symbols commonly found in templating languages.
This issue most frequently appears when a server-side or client-side templating engine (such as Mustache, Handlebars, Angular, Jinja2, or Blade) fails to fully process its expressions before the HTML reaches the browser. Instead of the template placeholder being replaced with a proper value, the raw template syntax ends up in the HTML as a malformed attribute. For example, {{class}} might appear as an attribute name rather than being resolved to its intended value.
Why this matters
- Standards compliance: HTML that isn't serializable as XML 1.0 cannot be reliably converted to XHTML, which limits interoperability.
- Browser inconsistency: Browsers may handle invalid attribute names unpredictably, potentially ignoring the attribute entirely or misinterpreting surrounding markup.
- Accessibility: Malformed attributes can break ARIA attributes or other accessibility-related markup, making content inaccessible to assistive technologies.
- Tooling and parsing: XML-based tools, RSS feeds, and content syndication systems that consume your HTML will choke on attributes that violate XML naming rules.
How to fix it
- Check for unresolved template expressions. Inspect the rendered HTML (not your source templates) for leftover placeholders like
{{...}},<%= ... %>,@{...}, or similar patterns. - Ensure proper server-side rendering. Make sure your templating engine is correctly processing all expressions before the HTML is sent to the client.
- Remove invalid characters from attribute names. If you're using custom attributes, stick to valid
data-*attributes with names consisting only of lowercase letters, digits, and hyphens (after thedata-prefix). - Check for typos. A missing
=sign, quote, or space can cause a value to be interpreted as an attribute name.
Examples
Unresolved template placeholder in an attribute
This occurs when a template expression isn't processed and appears literally in the output:
<!-- ❌ Bad: template syntax rendered as attribute name -->
<div {{classBinding}} id="main">
<p>Hello, world!</p>
</div>
The fix is to ensure the template engine resolves the expression. The rendered output should look like this:
<!-- ✅ Good: attribute properly resolved -->
<div class="container" id="main">
<p>Hello, world!</p>
</div>
Typo causing a value to be parsed as an attribute name
A missing equals sign or quotation mark can cause part of a value to become an attribute name with invalid characters:
<!-- ❌ Bad: missing = sign causes "bold}" to be treated as an attribute -->
<p style"font-weight:bold}" class="intro">Welcome</p>
<!-- ✅ Good: proper attribute syntax -->
<p style="font-weight:bold" class="intro">Welcome</p>
Special characters in custom attribute names
Using invalid characters directly in attribute names will trigger this error:
<!-- ❌ Bad: @ and $ are not valid in attribute names -->
<input @change="update" $value="test">
If you need custom attributes, use the standard data-* pattern:
<!-- ✅ Good: valid data attributes -->
<input data-change="update" data-value="test">
Angular-style bindings in static HTML
Frameworks like Angular use special attribute syntax (e.g., [property] or (event)) that is only valid within the framework's context and will fail validation if rendered directly:
<!-- ❌ Bad: framework-specific syntax in raw HTML -->
<img [src]="imageUrl" (load)="onLoad()">
If you're generating static HTML, use standard attributes instead:
<!-- ✅ Good: standard HTML attribute -->
<img src="photo.jpg" alt="A photo">
Every HTML element has a defined set of attributes it accepts. The HTML specification maintains strict rules about which attributes belong on which elements. For example, the href attribute is valid on an <a> element but not on a <div>. The for attribute belongs on <label> and <output> elements but not on <span>. When you place an attribute on an element that doesn't recognize it, the validator flags the error.
This issue matters for several reasons. First, browsers may silently ignore unrecognized attributes, meaning your code might appear to work but isn't actually doing anything — leading to hard-to-diagnose bugs. Second, assistive technologies like screen readers rely on valid HTML to correctly interpret page structure and behavior. Invalid attributes can confuse these tools and degrade accessibility. Third, standards-compliant HTML ensures consistent behavior across all browsers and future-proofs your code.
There are several common causes of this error:
- Typos or misspellings — Writing
hieghtinstead ofheight, orscrinstead ofsrc. - Attributes on the wrong element — Using
placeholderon a<div>instead of an<input>or<textarea>. - Obsolete attributes — Using presentational attributes like
align,bgcolor, orborderthat have been removed from the HTML specification in favor of CSS. - Framework-specific attributes — Using attributes like
ng-click(Angular),v-if(Vue), or@click(Vue shorthand) that aren't part of standard HTML. These frameworks typically process them before the browser sees them, but the raw HTML won't validate. - Custom attributes without the
data-*prefix — Inventing your own attributes liketooltiporstatuswithout following thedata-*convention. - ARIA attributes with typos — Writing
aria-roleinstead of the correctrole, oraria-labelledinstead ofaria-labelledby.
Examples
Attribute used on the wrong element
The placeholder attribute is only valid on <input> and <textarea> elements:
<!-- ❌ "placeholder" not allowed on "div" -->
<div placeholder="Enter text here">Content</div>
<!-- ✅ Use placeholder on a supported element -->
<input type="text" placeholder="Enter text here">
Obsolete presentational attribute
The align attribute has been removed from most elements in HTML5. Use CSS instead:
<!-- ❌ "align" not allowed on "div" -->
<div align="center">Centered content</div>
<!-- ✅ Use CSS for presentation -->
<div style="text-align: center;">Centered content</div>
Custom attribute without data-* prefix
If you need to store custom data on an element, use the data-* attribute format:
<!-- ❌ "tooltip" not allowed on "span" -->
<span tooltip="More information">Hover me</span>
<!-- ✅ Use a data-* attribute for custom data -->
<span data-tooltip="More information">Hover me</span>
The data-* attributes are specifically designed for embedding custom data. You can access them in JavaScript via the dataset property, e.g., element.dataset.tooltip.
Misspelled attribute
A simple typo can trigger this error:
<!-- ❌ "widht" not allowed on "img" -->
<img src="photo.jpg" widht="300" alt="A photo">
<!-- ✅ Correct the spelling -->
<img src="photo.jpg" width="300" alt="A photo">
ARIA attribute typo
ARIA attributes must match their exact specification names:
<!-- ❌ "aria-labelled" not allowed on "input" -->
<input type="text" aria-labelled="name-label">
<!-- ✅ Use the correct ARIA attribute name -->
<input type="text" aria-labelledby="name-label">
Framework-specific attributes
If you're using a JavaScript framework and want your source templates to validate, be aware that framework-specific syntax won't pass validation. In Vue, for example, you can use the data-* equivalent or accept that templates are preprocessed:
<!-- ❌ "v-if" not allowed on "div" -->
<div v-if="isVisible">Hello</div>
<!-- This is expected with Vue templates and is typically not a concern,
since the framework processes these before they reach the browser. -->
When encountering this error, check the MDN Web Docs reference for the element in question to see which attributes it actually supports. This will quickly clarify whether you need to fix a typo, move the attribute to a different element, replace it with CSS, or convert it to a data-* attribute.
The xmlns:cc attribute declares the Creative Commons namespace used in SVG metadata, and HTML doesn't allow prefixed namespace declarations on <svg> or any other element.
Files saved by Inkscape often have xmlns:cc="http://creativecommons.org/ns#" on the root <svg> element. The prefix is for the Creative Commons terms in the file's RDF metadata. <cc:Work> wraps the description of the drawing, and if you pick a license under Document Properties, <cc:license> records it. In a standalone .svg file, which is XML, the declaration is valid. The error shows up when that markup ends up inside an HTML page, pasted by hand or inlined by a template or build step.
The HTML parser doesn't process namespace declarations, so xmlns:cc stays a plain attribute with a colon in its name. The validator rejects it on <svg>, and on <html> or <div> too. On <svg> it accepts just two namespace attributes, xmlns and xmlns:xlink. Inkscape exports usually put xmlns:cc next to xmlns:dc, xmlns:rdf, xmlns:sodipodi and xmlns:inkscape, and each of those gets its own message.
Delete xmlns:cc from the <svg> tag, and delete the <metadata> block with it. The cc: elements in that block break for the same parser reason. <cc:Work> becomes an SVG element whose name happens to contain a colon, and the validator reports cc:work and cc:license as completely-unknown elements in SVG content. None of the metadata is drawn, so the image doesn't change.
That block may be the only place the file states its license. If the license matters, keep the original .svg, metadata and all, in your source files, and show the license where readers can see it, such as in a caption under the image.
To stop the declaration from coming back, optimize the SVG before it gets inlined. SVGO's default preset runs removeEditorsNSData, which removes the Creative Commons namespace along with the Inkscape and Sodipodi ones, and removeMetadata, which removes the <metadata> block.
Invalid example
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
width="120" height="120" viewBox="0 0 24 24">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<cc:license rdf:resource="https://creativecommons.org/licenses/by/4.0/" />
</cc:Work>
</rdf:RDF>
</metadata>
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
Valid example
<figure>
<svg width="120" height="120" viewBox="0 0 24 24" role="img">
<title>Checkmark</title>
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
<figcaption>
Icon licensed under <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
</figcaption>
</figure>
The xmlns:dt attribute — short for "XML Namespace: datatypes" — was historically used in Microsoft-specific XML vocabularies (notably urn:schemas-microsoft-com:datatypes) to declare data type information on elements. It was common in older ASP and IE-era markup. However, HTML5 is not an XML language, and it does not support arbitrary XML namespace declarations on elements.
In HTML5, the only xmlns attribute permitted is xmlns="http://www.w3.org/1999/xhtml" on the <html> element itself, and even that exists solely for compatibility with XHTML serialization. Namespace-prefixed attributes like xmlns:dt, xmlns:o, or xmlns:v are invalid. The HTML parser simply does not recognize them, and the W3C validator will flag them with the error "Attribute 'xmlns:dt' not allowed here."
Why This Is a Problem
- Standards compliance: Using non-standard attributes means your document does not conform to the HTML specification, which can lead to unpredictable behavior across browsers.
- Legacy lock-in: The
xmlns:dtattribute is tied to Microsoft's proprietary data type schema. Modern browsers do not interpret or use this namespace, so it serves no functional purpose in an HTML5 document. - Validation noise: Invalid attributes generate validator errors that can obscure real issues in your markup, making it harder to catch genuine bugs.
- Accessibility and tooling: Screen readers, search engine crawlers, and other automated tools expect valid HTML. Non-standard attributes can confuse parsers or be silently discarded.
How to Fix It
- Remove the attribute. If
xmlns:dtwas carried over from legacy code or a CMS template and nothing in your application depends on it, simply delete it. - Replace with
data-*attributes. If you need to attach custom metadata to an element — for example, to indicate a data type for use by JavaScript — use an HTML5data-*attribute instead. - Use XHTML if XML namespaces are required. If you genuinely need XML namespace support (rare in modern web development), serve your document as
application/xhtml+xmlwith a proper XHTML doctype and XML declaration. Be aware this changes parsing rules significantly.
Examples
Incorrect: Using xmlns:dt in HTML5
This will trigger the validation error:
<ul xmlns:dt="urn:schemas-microsoft-com:datatypes">
<li dt:dt="string">Item one</li>
<li dt:dt="number">42</li>
</ul>
Both xmlns:dt on the <ul> and the dt:dt attributes on the <li> elements are invalid in HTML5.
Correct: Attribute removed
If the namespace declaration is unnecessary (which it almost always is in modern HTML), remove it along with any prefixed attributes:
<ul>
<li>Item one</li>
<li>42</li>
</ul>
Correct: Using data-* attributes for custom metadata
If your JavaScript or application logic needs to know the data type of each item, use valid data-* attributes:
<ul>
<li data-type="string">Item one</li>
<li data-type="number">42</li>
</ul>
You can then access these values in JavaScript with element.dataset.type.
Correct: Migrating a legacy div wrapper
A common legacy pattern places xmlns:dt on a container div:
<!-- Invalid -->
<div xmlns:dt="urn:schemas-microsoft-com:datatypes">
<span dt:dt="dateTime">2024-01-15</span>
</div>
The fixed version removes the namespace and uses standard attributes:
<div>
<time datetime="2024-01-15">January 15, 2024</time>
</div>
In this case, the semantic <time> element with its datetime attribute is the proper HTML5 way to represent date and time values — no custom namespace needed.
Quick Checklist
- Search your codebase for
xmlns:dtand anydt:prefixed attributes. - Check CMS templates, server-generated markup, and copy-pasted legacy code — these are the most common sources.
- Remove the attributes or replace them with
data-*equivalents. - Re-validate your document to confirm the error is resolved.
The xmlns:inkscape attribute declares the namespace Inkscape uses for its own editor data, and HTML doesn't allow prefixed namespace declarations on <svg> or any other element.
Inkscape's default file format, Inkscape SVG, puts xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" on the root <svg> element. The prefix marks attributes that only Inkscape reads: inkscape:version records the release that saved the file, and inkscape:groupmode="layer" with an inkscape:label turns a <g> into a named layer. Inkscape 0.92 also writes inkscape:connector-curvature="0" on paths, and inkscape:export-filename remembers where the last PNG export went. Browsers ignore all of them, so the image looks the same without them.
In an HTML page the declaration does nothing. The HTML parser doesn't handle namespace prefixes, so xmlns:inkscape is a plain attribute with a colon in its name, and the validator reports it on any element that carries it. Each inkscape: attribute gets its own message as well, such as Attribute "inkscape:version" not allowed on element "svg" at this point. Inkscape SVG files usually declare xmlns:sodipodi next to it, for attributes like sodipodi:docname, and the validator reports that declaration separately.
Delete xmlns:inkscape and every attribute that starts with inkscape:. Removing only the declaration leaves the attribute errors behind. The layers turn into plain groups and lose their labels, so if a stylesheet or script needs to find one, use the group's id (Inkscape assigns ids like layer1) or add a class.
When you clean up a standalone .svg file, remove the declaration and the attributes together. Delete xmlns:inkscape but leave a single inkscape:label behind, and the file stops being well-formed XML, because it uses a prefix it never declares. Browsers then refuse to display it (Firefox reports an "unbound prefix").
To get a copy without the Inkscape markup, use File > Save a Copy and choose Optimized SVG or Plain SVG. Optimized SVG runs Scour, which strips editor data unless you check its "Keep editor data" option. Plain SVG drops the inkscape: and sodipodi: markup but still writes xmlns:svg, which the validator also rejects.
Keep the Inkscape SVG as the file you edit. A copy without the editor data reopens without its layers, and shapes drawn with the star tool come back as plain paths. If a build step inlines your SVGs, SVGO removes the same markup with removeEditorsNSData, which is part of its default preset.
Invalid example
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.3.2"
width="24" height="24" viewBox="0 0 24 24">
<g inkscape:label="Icon" inkscape:groupmode="layer" id="layer1">
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</g>
</svg>
Valid example
<svg xmlns="http://www.w3.org/2000/svg"
width="24" height="24" viewBox="0 0 24 24">
<g id="layer1">
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</g>
</svg>
The xmlns:msdt attribute is a Microsoft Office namespace declaration, and HTML doesn't allow prefixed namespace declarations on any element.
In XML, xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" binds the prefix msdt to Microsoft's data types namespace. Office uses it to give each document property a type, with attributes like msdt:dt="string". The HTML parser doesn't process namespace declarations, so it reads xmlns:msdt as an unknown attribute that happens to have a colon in its name. The only namespace attribute HTML accepts is xmlns, with the exact value http://www.w3.org/1999/xhtml. The validator reports xmlns:msdt on any element, <html> included.
The declaration usually comes with a block of Office document properties, which SharePoint and Office write into the pages they save. The block has its own <html> and <head> tags, often with xmlns:mso next to xmlns:msdt, and keeps the properties inside a conditional comment that browsers treat as a plain comment. When the block ends up in the middle of a page, the validator also reports the stray <html> and <head> tags. Browsers drop the extra <head> tags and copy the attributes of the extra <html> tag onto the page's real <html> element.
Remove the whole block: the extra <html> and <head> tags and the comment between them. If xmlns:msdt sits on the page's own <html> tag instead, delete just the attribute. Browsers don't use the declaration or the properties, so the page looks and works the same without them. If the block comes from a SharePoint page layout, remove it from the layout so every page that uses it gets the fix. If it comes from content pasted into a web part, edit that content.
Invalid example
<div class="page-content">
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"><head>
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:ContentType msdt:dt="string">Page</mso:ContentType>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<p>Our offices are open Monday to Friday.</p>
</div>
Valid example
<div class="page-content">
<p>Our offices are open Monday to Friday.</p>
</div>
The xmlns:mso attribute is an XML namespace declaration that SharePoint writes into the pages and files it stores, and HTML doesn't accept it on any element.
In XML, xmlns:mso="urn:schemas-microsoft-com:office:office" binds the prefix mso to the Microsoft Office namespace, the same namespace Word binds to o. SharePoint uses that prefix for page properties such as the content type or the contact name, stored as mso: elements inside <mso:CustomDocumentProperties>.
HTML elements don't take namespace declarations. The parser treats xmlns:mso as an ordinary attribute that happens to have a colon in its name, and no HTML element defines an attribute by that name. The one namespace attribute an HTML element may carry is xmlns, and only with the value http://www.w3.org/1999/xhtml, so the validator reports xmlns:mso even on the page's own <html> tag.
Most of the time the attribute arrives inside a block of SharePoint properties that ends up in the page: a second <html> tag with xmlns:mso (often next to xmlns:msdt), a <head> tag, and the properties wrapped in a <!--[if gte mso 9]> conditional comment. The mso in that comment is Office's version check, unrelated to the namespace prefix, and browsers read the whole comment as a plain comment. When the block sits inside the body, the validator also reports the stray <html> and <head> tags. Browsers skip the extra <head> tags and copy the extra <html> tag's attributes onto the page's real <html> element.
Delete the whole block: the extra <html> and <head> tags and the comment between them. If xmlns:mso is on the page's own <html> tag, delete only the attribute. Browsers ignore the declaration and the properties, so removing them doesn't change how the page looks or behaves. Edit the file the block lives in. When every page built from the same page layout or master page shows it, fix that layout or master page. When only one page has it, look in the HTML file or web part content that page pulls in.
Invalid example
<div class="page-content">
<html xmlns:mso="urn:schemas-microsoft-com:office:office"><head>
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:PublishingContactName>Web team</mso:PublishingContactName>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<p>Our offices are open Monday to Friday.</p>
</div>
Valid example
<div class="page-content">
<p>Our offices are open Monday to Friday.</p>
</div>
The xmlns:pcm attribute is an XML namespace declaration, and HTML doesn't allow prefixed namespace declarations on any element.
In XML, xmlns:pcm="urn:PageContentManager" binds the prefix pcm to that namespace, so names like pcm:item can appear inside the element. The HTML parser doesn't process namespace declarations. It keeps xmlns:pcm as a plain attribute with a colon in its name. The only namespace attribute an HTML element may have is xmlns, with the exact value http://www.w3.org/1999/xhtml. The validator reports xmlns:pcm wherever it appears, <html> included.
The attribute shows up in pages built with XSLT, such as SharePoint web parts. When an XSLT stylesheet writes out a literal element, it copies the namespace declarations in scope onto that element, except for the XSLT namespace itself and any prefix listed in exclude-result-prefixes. If you can edit the stylesheet, add pcm to that list:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pcm="urn:PageContentManager"
exclude-result-prefixes="pcm">
Browsers do nothing with the attribute, so removing it doesn't change how the page looks or works.
Invalid example
<div class="news-list" xmlns:pcm="urn:PageContentManager">
<ul>
<li><a href="/news/opening-hours">Opening hours change</a></li>
</ul>
</div>
Valid example
<div class="news-list">
<ul>
<li><a href="/news/opening-hours">Opening hours change</a></li>
</ul>
</div>
The xmlns:rdf attribute declares the RDF namespace that SVG editors use for the metadata block in a drawing, and HTML doesn't allow prefixed namespace declarations on <svg> or any other element.
Inkscape SVG files, such as those saved by Inkscape 0.92, declare xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" on the root <svg> element, next to xmlns:dc and xmlns:cc. RDF (Resource Description Framework) is the W3C model for describing things as statements, and the rdf: namespace holds its core terms. Inkscape uses them to build the <metadata> block. <rdf:RDF> wraps the description, rdf:about="" says it is about this file, and rdf:resource gives a property a URI as its value, such as the Dublin Core type StillImage. The title and format are Dublin Core (dc:) terms, and the license is a Creative Commons (cc:) one. In a standalone .svg file, which is XML, all of this is valid.
Inline the file in an HTML page and the block stops being RDF. The HTML parser doesn't process namespace declarations, so xmlns:rdf is a plain attribute with a colon in its name, and the validator reports it on <svg>, on <html> and on any other element. The elements lose their namespace too. <rdf:RDF> becomes an SVG element named rdf:rdf, which the validator reports as a completely-unknown element, along with every element nested in it.
Delete xmlns:rdf together with the <metadata> block. Removing only the declaration leaves all those unknown-element errors in place. Nothing in the block is drawn, so the image doesn't change. The same export usually declares xmlns:dc, xmlns:cc, xmlns:sodipodi and xmlns:inkscape too. Each gets its own message, and they all go in the same cleanup.
If the page needs machine-readable facts about the image, such as who made it or what license it has, describe it in JSON-LD instead. A <script type="application/ld+json"> block with a schema.org ImageObject can hold creator and license, and its contentUrl points at the image file, for example the original .svg with its metadata intact. Google's image metadata documentation asks for contentUrl plus at least one of creator, creditText, copyrightNotice or license.
On <html>, xmlns:rdf is a leftover from XHTML+RDFa 1.0, which declared prefixes with xmlns:. RDFa 1.1 uses the prefix attribute instead, and rdf is one of its predefined prefixes, so you can delete the declaration without adding anything in its place.
To keep the declaration out of inlined SVGs, run them through SVGO first. Its default preset includes removeEditorsNSData, whose list of editor namespaces contains RDF, and removeMetadata, which drops the <metadata> block.
Invalid example
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
width="240" height="160" viewBox="0 0 240 160">
<metadata>
<rdf:RDF>
<rdf:Description rdf:about="">
<dc:title>Route map</dc:title>
<dc:creator>Jane Doe</dc:creator>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</rdf:Description>
</rdf:RDF>
</metadata>
<path d="M20 140L120 20L220 140" fill="none" stroke="currentColor" stroke-width="4" />
</svg>
Valid example
<svg width="240" height="160" viewBox="0 0 240 160" role="img">
<title>Route map</title>
<path d="M20 140L120 20L220 140" fill="none" stroke="currentColor" stroke-width="4" />
</svg>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ImageObject",
"contentUrl": "https://example.com/images/route-map.svg",
"name": "Route map",
"creator": { "@type": "Person", "name": "Jane Doe" },
"license": "https://creativecommons.org/licenses/by/4.0/"
}
</script>
The xmlns:sketch attribute declares the namespace the Sketch design app used for its layer data, and HTML doesn't allow prefixed namespace declarations on <svg> or any other element.
Sketch is a macOS design app from Bohemian Coding. Until version 3.6, it put xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" on the root <svg> of every SVG it exported. The prefix is there for the sketch:type attributes, which record what each element was in the Sketch document: MSPage on the page group, MSArtboardGroup on the artboard, MSLayerGroup on a group of layers and MSShapeGroup on each shape. Sketch 3.6, released in March 2016, dropped these prefixes to make its SVG exports smaller. An SVG that still carries them was exported before then and ended up in a page or template later.
The HTML parser doesn't handle namespace prefixes, so xmlns:sketch is a plain attribute with a colon in its name. The validator reports it on any element that carries it, whether that's <svg> or a <div>. Each sketch:type gets its own message too, such as Attribute "sketch:type" not allowed on element "path" at this point. Browsers ignore this markup, so removing it doesn't change how the icon looks.
Delete xmlns:sketch and every sketch:type attribute. Removing only the declaration leaves one error per sketch:type behind. Delete them together in a standalone .svg file too: if a sketch:type survives without its declaration, the file is no longer well-formed XML and browsers won't display it.
Sketch's export also copies the layer name into <title> and adds <desc>Created with Sketch.</desc>. Neither one is a validation error. In inline SVG, though, the browser uses <title> as the image's accessible name and <desc> as its description, so a screen reader can announce "Created with Sketch." Give the <title> a name that describes the icon, and delete the <desc>.
If a build step inlines your SVG files, SVGO removes the Sketch markup for you. Its default preset runs removeEditorsNSData, and http://www.bohemiancoding.com/sketch/ns is on that plugin's list of editor namespaces, so it deletes the declaration and every sketch: attribute. The preset's removeDesc plugin deletes a <desc> that starts with "Created with".
Invalid example
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>check</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" fill="none" sketch:type="MSPage">
<g id="Icons" sketch:type="MSArtboardGroup">
<path d="M5 12l5 5L20 7" id="check" stroke="#000000" stroke-width="2" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>
Valid example
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Checkmark</title>
<g id="Page-1" stroke="none" fill="none">
<g id="Icons">
<path d="M5 12l5 5L20 7" id="check" stroke="#000000" stroke-width="2"></path>
</g>
</g>
</svg>
The xmlns:sodipodi attribute declares the namespace for editor data that Inkscape inherited from Sodipodi, and HTML doesn't allow prefixed namespace declarations on <svg> or any other element.
Sodipodi was a vector drawing program written mainly by Lauris Kaplinski, and SVG was its native file format. In 2003 a group of its developers forked it to start Inkscape. Sodipodi itself stopped at version 0.34, released in February 2004. Inkscape kept the sodipodi: prefix for the features it inherited, so files saved by current versions still declare xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" on the root <svg>. The URI is only a name for the namespace. Nothing downloads that DTD.
The prefix marks editor state. <sodipodi:namedview>, a child of the root <svg>, keeps the document's view settings: page and border colors, the grid, zoom and window position, the current layer, and any guide lines as <sodipodi:guide> children. On the root element, sodipodi:docname records the file name the drawing was last saved under.
Shapes and text carry their own sodipodi: attributes. sodipodi:nodetypes on a path has one letter per node (c for cusp, s for smooth, z for symmetric, a for auto-smooth), which the node tool reads to decide how a node's handles move. sodipodi:type marks a path drawn with a shape tool, such as star, arc or spiral, and attributes like sodipodi:sides and sodipodi:r1 keep the shape's parameters so Inkscape can bring its handles back. Lines of text get sodipodi:role="line" on their <tspan>. Browsers ignore all of it, and a star is drawn from the path's d attribute like any other path.
The HTML parser doesn't link prefixes to declarations. To it, xmlns:sodipodi is one attribute with a colon in its name and sodipodi:docname is another, and nothing connects the two. Delete only the declaration and every other sodipodi: name still fails on its own. The invalid example below gets 13 errors, and only one of them is about xmlns:sodipodi. The other 12 come from the sodipodi: attributes, such as Attribute "sodipodi:type" not allowed on element "path" at this point., and from <sodipodi:namedview> and <sodipodi:guide>, which the validator reports as completely-unknown elements in SVG content.
Delete xmlns:sodipodi, the <sodipodi:namedview> element with everything inside it, and every attribute that starts with sodipodi:. The image looks the same afterwards. Only Inkscape notices: the guides, grid and page settings are gone, and stars and spirals reopen as plain paths. Keep the original file for editing and put a cleaned copy in the page.
The same Inkscape file usually declares xmlns:inkscape, xmlns:rdf, xmlns:cc and xmlns:dc too, and each gets its own message. SVGO's removeEditorsNSData plugin, part of its default preset, removes the Sodipodi declaration and every sodipodi: element and attribute, and does the same for those four namespaces. If the whole file was pasted in, its <?xml version="1.0"?> line comes along too, and the validator reports it as an XML processing instruction.
Invalid example
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
sodipodi:docname="star.svg"
width="24" height="24" viewBox="0 0 24 24">
<sodipodi:namedview pagecolor="#ffffff" showgrid="false">
<sodipodi:guide position="12,12" orientation="1,0" />
</sodipodi:namedview>
<path sodipodi:type="star" sodipodi:sides="5"
sodipodi:cx="12" sodipodi:cy="12" sodipodi:r1="10" sodipodi:r2="4"
sodipodi:arg1="-1.5708" sodipodi:arg2="-0.9425"
d="M12,2 14.35,8.76 21.51,8.91 15.8,13.24 17.88,20.09 12,16 6.12,20.09 8.2,13.24 2.49,8.91 9.65,8.76Z"
fill="currentColor" />
</svg>
Valid example
<svg xmlns="http://www.w3.org/2000/svg"
width="24" height="24" viewBox="0 0 24 24">
<path d="M12,2 14.35,8.76 21.51,8.91 15.8,13.24 17.88,20.09 12,16 6.12,20.09 8.2,13.24 2.49,8.91 9.65,8.76Z"
fill="currentColor" />
</svg>
The xmlns:style attribute declares an XML namespace prefix, and HTML elements don't accept namespace declarations other than xmlns itself.
In XML, xmlns:style="..." binds the prefix style to a namespace URI, so the document can use names like style:font. The HTML parser doesn't process namespace declarations. It reads xmlns:style as an ordinary attribute with an unusual name and does nothing with it. The one namespace attribute an HTML element may have is xmlns, and only with the exact value http://www.w3.org/1999/xhtml. The validator rejects prefixed declarations like xmlns:style on every HTML element, <html> included.
The attribute usually comes from markup generated with XML tools. An XSLT stylesheet, for example, copies the namespace declarations in scope onto each literal element it outputs, unless the prefix is listed in exclude-result-prefixes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:style="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="style">
When a template repeats the declaration on the same element, the validator also reports a duplicate attribute error. Removing xmlns:style fixes both, and the page renders the same because the attribute has no effect in browsers.
Invalid example
<div class="top-bar" xmlns:style="http://www.w3.org/1999/xhtml">
<a href="/">Home</a>
</div>
Valid example
<div class="top-bar">
<a href="/">Home</a>
</div>
The xmlns:web attribute is an XML namespace declaration for a web prefix, and HTML doesn't allow prefixed namespace declarations on any element.
In XML, xmlns:web="http://example.com/schemas/web/" binds the prefix web to a namespace, so names like web:result can appear in the document. The URI identifies the namespace, and web is only a short alias the template's author picked. On the root <html> tag, the declaration is typically left over from a template first written as XHTML, where it sat next to xmlns="http://www.w3.org/1999/xhtml" and xml:lang.
The HTML parser doesn't process namespace declarations. It keeps xmlns:web as a plain attribute with a colon in its name, and it lowercases the name, so the validator reports xmlns:web even when the source says xmlns:Web. The only namespace attribute HTML accepts is xmlns, with the exact value http://www.w3.org/1999/xhtml. That one is allowed but does nothing in an HTML page, so you can keep it or drop it.
Delete xmlns:web from the tag. Browsers don't act on the declaration, so removing it doesn't change how the page looks or works. If the markup also has web: attributes, the validator reports each of them as not allowed. Move that data into data-* attributes, or remove it if nothing reads it.
Invalid example
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:Web="http://example.com/schemas/web/">
<head>
<title>Search results</title>
</head>
<body>
<p>Results for your search.</p>
</body>
</html>
Valid example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Search results</title>
</head>
<body>
<p>Results for your search.</p>
</body>
</html>
An attribute like xmlns:news or xmlns:x declares an XML namespace prefix, and HTML doesn't accept prefixed namespace declarations, except xmlns:xlink on SVG and MathML elements.
In XML, xmlns:news="http://example.com/modules/news" binds the prefix news to a namespace URI, so names like news:item can appear in the document. The HTML parser doesn't process namespace declarations. It keeps the declaration as a plain attribute with a colon in its name, and it lowercases that name, so xmlns:Foo in the source shows up as xmlns:foo in the message. The validator reports it the same way whatever the prefix is and whichever element carries it, <html> included. On HTML elements the only namespace attribute allowed is xmlns, with the exact value http://www.w3.org/1999/xhtml. Inline <svg> and <math> also accept xmlns:xlink="http://www.w3.org/1999/xlink", and no other prefix.
Pages built with XSLT, as many CMS modules are, often carry these declarations on a <div> or on <html>. When an XSLT stylesheet writes out a literal element, it copies the namespace declarations in scope onto that element, except for the XSLT namespace itself and any prefix listed in exclude-result-prefixes. If you can edit the stylesheet, add the prefix to that list:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:news="http://example.com/modules/news"
exclude-result-prefixes="news">
Inline SVG pasted from Adobe Illustrator brings its own set: xmlns:x, xmlns:i and xmlns:graph on the root <svg>, pointing to Adobe's Extensibility, Illustrator and Graphs namespaces, and in older files xmlns:a for the Adobe SVG Viewer plugin. In the original .svg file the values are often entity references like &ns_ai;, defined in the file's DOCTYPE, so they don't resolve to anything once the markup sits inside an HTML page. Delete the declarations along with any attributes that use those prefixes, such as i:extraneous="self" on a <g>, which the validator reports as a separate error. If a build step inlines your SVGs, SVGO's removeEditorsNSData plugin, part of its default preset, removes Adobe's namespaces and the attributes that use them.
Browsers ignore these declarations in HTML, so removing them doesn't change how the page looks or works.
Invalid example
<div class="news-list" xmlns:news="http://example.com/modules/news">
<p>Latest news</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:x="http://ns.adobe.com/Extensibility/1.0/"
xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/"
xmlns:graph="http://ns.adobe.com/Graphs/1.0/"
width="24" height="24" viewBox="0 0 24 24">
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
Valid example
<div class="news-list">
<p>Latest news</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg"
width="24" height="24" viewBox="0 0 24 24">
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
A < character appearing where an attribute name is expected typically means a closing > is missing on the previous tag, causing the browser to interpret the next tag as an attribute.
This error occurs when you forget to close an HTML element's opening tag with >. The validator sees the < of the next element and thinks it's still parsing attributes of the previous element. It's a common typo that can cascade into multiple confusing errors.
For example, if you write <div without the closing >, the following <p> tag gets parsed as if it were an attribute of the div, triggering this error.
HTML Examples
❌ Incorrect
<div class="container"
<p>Hello, world!</p>
</div>
The <div> tag is missing its closing > after "container", so the validator sees <p> as part of the div's attribute list.
✅ Correct
<div class="container">
<p>Hello, world!</p>
</div>
Make sure every opening tag is properly closed with >. If the error points to a specific line, check the tag immediately before that line for a missing >.
When the HTML parser encounters a tag's attributes, it expects a specific structure: an attribute name, followed by an equals sign, followed by a quoted value. If a quote character appears where the parser expects an attribute name, it means something has gone wrong in the syntax earlier in the tag. The validator flags this as Quote """ in attribute name and suggests that a matching quote is likely missing somewhere before.
This issue matters because browsers will try to recover from the malformed HTML in unpredictable ways. One browser might ignore the attribute entirely, while another might merge it with adjacent text. This can lead to broken styling, missing functionality, or elements that behave differently across browsers. For accessibility, malformed attributes can prevent assistive technologies from correctly interpreting element semantics and roles.
There are several common causes for this error:
- Missing equals sign between an attribute name and its value, causing the parser to treat the opening quote as part of the attribute name.
- Extra closing quote that prematurely ends an attribute value, leaving subsequent quotes orphaned.
- Unescaped quotes inside attribute values, which break the quoting structure of the entire tag.
- Copy-paste errors that introduce curly/smart quotes (
"") or extra quote characters. - A missing closing quote on a previous attribute, causing the parser to consume subsequent attributes as part of that value.
Examples
Missing equals sign
The most common cause. Without the =, the parser sees class as one attribute and then encounters " where it expects another attribute name.
❌ Incorrect:
<p class"news">This paragraph has broken markup.</p>
✅ Fixed:
<p class="news">This paragraph has correct markup.</p>
Missing closing quote on a previous attribute
When a quote is left unclosed, everything after it—including other attributes—gets consumed as part of the value, until the parser eventually encounters another quote in an unexpected position.
❌ Incorrect:
<a href="/about class="link">About us</a>
Here, the href value is never closed. The parser reads /about class= as the href value, then encounters "link" in an unexpected context.
✅ Fixed:
<a href="/about" class="link">About us</a>
Extra quote character
A stray extra quote breaks the pairing of subsequent quotes.
❌ Incorrect:
<div id=""main" class="container">Content</div>
✅ Fixed:
<div id="main" class="container">Content</div>
Unescaped quotes inside an attribute value
If the attribute value itself contains a double quote, it must be escaped as " or the attribute must use single quotes instead.
❌ Incorrect:
<input type="text" value="She said "hello"">
✅ Fixed (using "):
<input type="text" value="She said "hello"">
✅ Also fixed (using single quotes for the attribute):
<input type="text" value='She said "hello"'>
Smart/curly quotes from copy-paste
Word processors and rich-text editors often convert straight quotes to curly quotes, which are not valid for HTML attribute delimiters.
❌ Incorrect:
<p class="highlight">Styled text</p>
✅ Fixed:
<p class="highlight">Styled text</p>
How to debug this issue
When you see this error, the validator usually points to a specific line number, but the root cause may be on that line or earlier in the same tag. Follow these steps:
- Go to the line indicated by the validator and examine the full tag.
- Check every attribute on that element for proper
name="value"syntax. - Count the quotes — each attribute value should have exactly one opening and one closing quote.
- Look for missing
=signs between attribute names and their values. - Search for curly quotes (
",",',') and replace them with straight quotes ("or'). - If the line looks correct, check the preceding lines — an unclosed quote on a previous element can cascade errors into later markup.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries