HTML Guides for custom elements
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 is attribute on the <a> element is present but set to an empty string. This attribute names a customized built-in element, so it must hold a valid custom element name and cannot be empty.
The is attribute tells the browser to upgrade a standard element into a customized built-in element. You register one in JavaScript with customElements.define("fancy-link", FancyLink, { extends: "a" }), then write <a is="fancy-link"> to apply it. The value has to match a registered custom element name, which is always non-empty and contains a hyphen. An empty is="" names nothing, so the validator rejects it.
In practice this usually comes from a template that prints is="" when the variable feeding it is blank. If the element is not meant to be a customized built-in, remove the is attribute entirely. If it is, set the name of the element you registered.
Note that Safari does not support customized built-in elements, so many projects avoid is and use autonomous custom elements (a hyphenated tag such as <fancy-link>) instead.
Invalid example
<a is="" href="/pricing">Pricing</a>
Valid example
Remove is when the link is an ordinary anchor:
<a href="/pricing">Pricing</a>
Or give it the name of a registered customized built-in element:
<a is="fancy-link" href="/pricing">Pricing</a>
HTML does not define the element named in this message, and its name does not qualify as a custom element, so the validator rejects it wherever it appears.
Browsers still show the content of an unknown tag. They treat the tag as a generic inline element with no default styling, no meaning and no accessibility role, so its text renders as if the tag weren't there. The validator reports it because nothing in the HTML standard says what the element is.
The same tag also triggers a second error, Element "X" not allowed as child of element "Y" in this context, and the fix below clears both. The validator writes the element name in lowercase, so <st1:City> is reported as st1:city.
Most unknown elements come from one of these sources:
- A typo in a real element name, such as
<buton>or<sectoin>. - Markup left behind by Microsoft Word when a document is saved as HTML or pasted into an editor. Word adds tags with a namespace prefix:
<o:p>around paragraph content,<w:...>for document settings, and "smart tags" like<st1:place>,<st1:city>or<st1:metricconverter>around places, dates and measurements. - Tag names invented for styling or scripting, such as
<tabs>or<icon>, or placeholders from a widget or template engine that were never replaced.
Correct the name if it's a typo. For Word markup, delete the tags and keep the text inside them, since the wrapper does nothing in a browser. Most editors and CMSs have a "paste as plain text" option that keeps this markup out in the first place.
If you need an element of your own, give it a custom element name: lowercase, starting with a letter, and containing a hyphen, such as <unit-converter>. The validator accepts that name, and you can define its behavior with customElements.define().
Invalid example
<p>The table is <st1:metricconverter productid="120 cm">120 cm</st1:metricconverter> wide.</p>
<buton type="button">Add to cart</buton>
Valid example
<p>The table is 120 cm wide.</p>
<button type="button">Add to cart</button>
Valid example with a custom element
<p>The table is <unit-converter value="120" unit="cm">120 cm</unit-converter> wide.</p>
<script>
customElements.define("unit-converter", class extends HTMLElement {});
</script>
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