Environment
Vuetify Version: 4.1.8
Vue Version: 3.5.38
Browsers: Chrome
OS: Linux
Steps to reproduce
Render any chip and run the page through the W3C validator:
<v-chip text="Territoires (7)" />
Expected Behavior
Valid HTML. VChip defaults its root tag to span (makeTagProps({ tag: 'span' })), so a chip is an inline box by design and everything it renders inside should be phrasing content.
Actual Behavior
The root is a span as expected, and the overlay and underlay wrappers are spans too — but four wrappers are hardcoded as div: v-chip__filter, v-chip__prepend, v-chip__content and v-chip__append.
<span class="v-chip v-chip--label v-chip--link ...">
<span class="v-chip__overlay"></span>
<span class="v-chip__underlay"></span>
<div class="v-chip__content">…</div> <!-- invalid: div inside span -->
</span>
The validator reports, once per chip:
Element “div” not allowed as child of element “span” in this context.
Seven occurrences on a single page of our portal, all of them plain filter chips.
How this differs from #23093
#23093 (VBadge) only produces invalid HTML when the badge is placed inside phrasing content, e.g. inside VBtn's span.v-btn__content, and fixing it needs a discussion about the tag default because a badge legitimately wraps block content sometimes.
VChip has no such ambiguity: its root is already a span, so its subtree is already required to be phrasing content. The div wrappers are invalid unconditionally, with no particular nesting needed to trigger it.
Suggested fix
Render all four as span, matching the sibling v-chip__overlay and v-chip__underlay. No visual change: VChip.sass declares display: inline-flex explicitly on .v-chip__content and on the .v-chip__filter/.v-chip__prepend/.v-chip__append group, so the tag name carries no layout meaning. The close button is untouched — it is a button, already valid phrasing content.
None of these wrappers is reachable from userland (tag only controls the root), so there is no workaround short of patching the package.
I have a PR ready for this.
Environment
Vuetify Version: 4.1.8
Vue Version: 3.5.38
Browsers: Chrome
OS: Linux
Steps to reproduce
Render any chip and run the page through the W3C validator:
<v-chip text="Territoires (7)" />Expected Behavior
Valid HTML.
VChipdefaults its roottagtospan(makeTagProps({ tag: 'span' })), so a chip is an inline box by design and everything it renders inside should be phrasing content.Actual Behavior
The root is a
spanas expected, and the overlay and underlay wrappers arespans too — but four wrappers are hardcoded asdiv:v-chip__filter,v-chip__prepend,v-chip__contentandv-chip__append.The validator reports, once per chip:
Seven occurrences on a single page of our portal, all of them plain filter chips.
How this differs from #23093
#23093 (
VBadge) only produces invalid HTML when the badge is placed inside phrasing content, e.g. insideVBtn'sspan.v-btn__content, and fixing it needs a discussion about thetagdefault because a badge legitimately wraps block content sometimes.VChiphas no such ambiguity: its root is already aspan, so its subtree is already required to be phrasing content. Thedivwrappers are invalid unconditionally, with no particular nesting needed to trigger it.Suggested fix
Render all four as
span, matching the siblingv-chip__overlayandv-chip__underlay. No visual change:VChip.sassdeclaresdisplay: inline-flexexplicitly on.v-chip__contentand on the.v-chip__filter/.v-chip__prepend/.v-chip__appendgroup, so the tag name carries no layout meaning. The close button is untouched — it is abutton, already valid phrasing content.None of these wrappers is reachable from userland (
tagonly controls the root), so there is no workaround short of patching the package.I have a PR ready for this.