Skip to content

Don't render for attribute on Label for non-labelable controls - #3884

Open
Mohith26 wants to merge 2 commits into
tailwindlabs:mainfrom
Mohith26:fix/radio-label-for-attribute
Open

Don't render for attribute on Label for non-labelable controls#3884
Mohith26 wants to merge 2 commits into
tailwindlabs:mainfrom
Mohith26:fix/radio-label-for-attribute

Conversation

@Mohith26

Copy link
Copy Markdown

Fixes #3883, reported by @fischi20.

When a Label sits next to a Radio or Checkbox inside a Field, Headless UI renders for="headlessui-control-..." pointing at the control, but those components render a <span role="radio">, and the HTML spec only allows for to reference labelable elements (button/input/select/textarea and friends). The result is invalid HTML that Chrome DevTools flags.

The fix makes Label verify after mount that its target is actually labelable (new isLabelableElement() util, styled after the existing isInteractiveElement()) and omit the for attribute otherwise. Accessibility is unchanged (aria-labelledby still links the pair), and label-click proxying now resolves the control via the id closure instead of the rendered attribute, so clicking the label still activates and focuses the radio. Native controls like Input keep their for, including during SSR.

CHANGELOG entry added under Unreleased. Three regression tests: for kept for Input, for dropped for Radio with aria-labelledby intact, and label-click still focuses the radio. Full @headlessui-react suite: 1071 passed, zero new failures. Note: @headlessui-vue likely has the same issue; happy to port the fix there if you want it in this PR.

Mohith26 added 2 commits July 28, 2026 20:43
The `for` attribute is only valid on labelable elements
(https://html.spec.whatwg.org/#category-label). Components such as
`Radio` and `Checkbox` render a `span` under the hood, which is not
labelable, so pointing the `Label`'s `for` attribute at it results in
invalid HTML.

We now verify that the element the `for` attribute points to is a
labelable element, and drop the attribute otherwise. Clicking the
`Label` still activates and focuses the control because the click
proxying now relies on the resolved id instead of the rendered `for`
attribute.

Fixes tailwindlabs#3883
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

@Mohith26 is attempting to deploy a commit to the Tailwind Labs Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@headlessui/react@2.2.10 label for attribute is incorrectly applied for radio buttons

1 participant