HTML Guides for custom element
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
A Vue template left in the page's HTML puts a name attribute on <transition-group>, and the validator warns because name only has a meaning on a short list of HTML elements.
Vue's <TransitionGroup> component animates items as they are added to or removed from a list. Its name prop sets the prefix of the CSS classes Vue applies during the animation, so name="fade" gives you fade-enter-active, fade-leave-to and so on. When Vue mounts onto markup that is already in the page (an in-DOM template, common when Vue is loaded from a CDN without a build step), the browser parses that markup first, and the validator checks it before Vue has compiled anything.
To an HTML parser, transition-group is an autonomous custom element, because its name contains a hyphen. HTML lets custom elements carry any attribute without a namespace, which is why this is a warning and not an error. The validator still reports name on every element outside the ones where HTML defines it: button, details, fieldset, form, iframe, input, map, meta, object, output, select, slot and textarea.
To clear the warning, keep Vue's template syntax out of the HTML the validator checks. With a build step, write the component as a single-file component (.vue), so the page only contains the rendered output. Without one, move the template into a <script type="text/x-template"> element and point the app's template option at its id. The validator doesn't check markup inside a script element, and Vue compiles the template the same way.
Because HTML permits the attribute on custom elements, keeping the in-DOM template and muting this warning in your reports is also a reasonable choice.
Invalid example
<div id="app">
<transition-group name="fade" tag="div">
<p>New message</p>
</transition-group>
</div>
Valid example
<div id="app"></div>
<script type="text/x-template" id="app-template">
<transition-group name="fade" tag="div">
<p>New message</p>
</transition-group>
</script>
<script>
Vue.createApp({ template: "#app-template" }).mount("#app");
</script>
The validator warns about a name attribute on a custom element, any element whose name contains a hyphen, because it only expects name on a short list of built-in HTML elements.
The validator checks name against a fixed list: button, details, fieldset, form, iframe, input, map, meta, object, output, select, slot and textarea. It makes no exception for custom elements. HTML itself is more permissive here: an autonomous custom element may carry any attribute without a namespace that its author gives a meaning to, which is why the message is a warning and not an error.
The attribute usually comes from a Web Component that reads data such as a person's name from name, or from a framework component written straight into the page's HTML, such as a Vue component in an in-DOM template. In the second case the browser parses the markup before the framework compiles it, so a name prop reaches the validator as a plain attribute.
One kind of custom element does use name the way HTML defines it. A form-associated custom element, whose class sets static formAssociated = true and reports its value through ElementInternals, takes part in forms like an input does, and the HTML standard lists name as its attribute for form submission and the form's elements API. The validator doesn't run your scripts, so it can't tell such an element apart from any other. If the element is form-associated, keep name and mute the warning in your reports.
For any other custom element, rename the attribute to one that HTML doesn't reserve, such as person-name or data-name, and update the code that reads it: the getAttribute() calls and observedAttributes list of a Web Component, or the prop declaration of a framework component.
Invalid example
<profile-card name="Ada Lovelace" job-title="Mathematician"></profile-card>
<script>
customElements.define("profile-card", class extends HTMLElement {
connectedCallback() {
this.textContent = this.getAttribute("name") + ", " + this.getAttribute("job-title");
}
});
</script>
Valid example
<profile-card person-name="Ada Lovelace" job-title="Mathematician"></profile-card>
<script>
customElements.define("profile-card", class extends HTMLElement {
connectedCallback() {
this.textContent = this.getAttribute("person-name") + ", " + this.getAttribute("job-title");
}
});
</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