Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My <label> has htmlFor matching an input's id, but jsx-a11y/label-has-associated-control still warns? #718

Closed
corysimmons opened this issue Jun 26, 2020 · 39 comments

Comments

@corysimmons
Copy link

image

@ljharb
Copy link
Member

ljharb commented Jun 26, 2020

The input needs to also be inside the label to satisfy the stricter form of the rule (which the airbnb config configures, for example).

@corysimmons
Copy link
Author

corysimmons commented Jun 26, 2020

Is that part of an a11y spec? That is... <label>s that nest text + <input>s are as equally valid as doing <label for="email">Email</label> and <input id="email" /> as siblings.

Not trying to be nitpicky, just seems strange that an a11y spec would run contrary to the HTML spec.

@ljharb
Copy link
Member

ljharb commented Jun 26, 2020

The purpose of the “both” requirement is to reflect actual devices in use. There are some that only support linking, some that only support nesting, and some that support either.

The only way to reach 100% of people - which is what a11y is all about - is by doing both, regardless of what some spec says.

@corysimmons
Copy link
Author

corysimmons commented Jun 29, 2020

some that only support nesting

Ah okay I didn't realize. Thanks for educating me @ljharb :)

@corysimmons
Copy link
Author

@adamwathan A lot of TailwindUI examples use this pattern. It's not a11y-friendly. ☝️ I think TailwindUI should default to nesting elements within <label>s.

@adamwathan
Copy link

Can you share some examples of devices that don’t properly relate labels and inputs without nesting?

@ljharb
Copy link
Member

ljharb commented Jun 30, 2020

@adamwathan If I recall (i might be getting this backwards) Dragon NaturallySpeaking, for example, only supports for-ID linking, even when labels are nested; and there's a number of assistive devices (not browsers, and probably older ones) that don't support for-ID linking at all.

@adamwathan
Copy link

Asked about this on Twitter and can’t find any evidence to support this is an issue. Only found the opposite in fact — that using both approaches at once causes new problems.

https://twitter.com/adamwathan/status/1277760447404560384?s=21

@corysimmons
Copy link
Author

@adamwathan Thanks for pinging your community about it.

Adrian Roselli seems to be the only person, so far, who has actually studied this in-depth:

He seems to think Dragon has problems with the nested version.

Anyone have any friends who own Dragon and could test this for us? I don't have an extra $100 lying around to buy Dragon (especially for this one-off thing).

If this widely used rule is getting this wrong, and Dragon is the most popular screenreading software, this would be important to fix.

@corysimmons corysimmons reopened this Jun 30, 2020
@ljharb
Copy link
Member

ljharb commented Jun 30, 2020

Dragon is the only implementation I'm aware of that can't handle simple nesting.

I have seen zero evidence that using both causes problems; one vague tweet in that thread doesn't constitute evidence.

Regardless of what you do, the other benefit of nesting is that it ensures the click/tap area is larger and intuitively encloses both the label and the input.

@corysimmons
Copy link
Author

corysimmons commented Jun 30, 2020

one vague tweet in that thread doesn't constitute evidence.

Fair enough. I don't know his credentials. His website being almost exclusively accessibility content makes me lean towards trusting him.

So far we have your sketchy memory claim vs some vague tweet.

I'd really like for someone to get in touch with anyone who has a copy of Dragon to confirm this. Anyone famous want to ping their Twitter followers to help? Or any company looking at this issue want to sponsor this project [that's used on trillions of websites] a Dragon license so @ljharb can 100% confirm/deny these things?

the other benefit of nesting is that it ensures the click/tap area is larger and intuitively encloses both the label and the input.

To be pedantic, <label for="..."> also handles clicking to focus the input, albeit <label> is inline by default so the click area is smaller (setting label { display: block; } in a base.css or reset would fix that).

@ljharb
Copy link
Member

ljharb commented Jun 30, 2020

when they're not nested, you have two clickable rectangles, often with confusing gaps in between, instead of one larger one with no gaps.

@adamwathan
Copy link

Purchasing a Dragon license wouldn't answer this question, Dragon has issues with nesting, we are looking for evidence of a browser/device that has issues with linking.

@corysimmons
Copy link
Author

There's some confusion.

If I recall (i might be getting this backwards) Dragon NaturallySpeaking, for example, only supports for-ID linking...
@ljharb

Dragon is the only implementation I'm aware of that can't handle simple nesting.
@ljharb

  • Jordan isn't sure which devices care about nesting.
  • I agree with Jordan that some random/vague Tweet probably isn't enough to base this on.
  • I think someone actually loading up Dragon and testing it out would let us solve this, and probably lots of other guesses that are sprinkled through eslint-plugin-jsx-a11y.
  • If eslint-plugin-jsx-a11y is used on tons of sites, and Dragon (the most popular accessibility software) can't read labels, then it's potentially screwing with lots of poor-vision people (particularly with forms). Seems worth investigating.

But I'm tired now and I have to go home.

@ljharb
Copy link
Member

ljharb commented Jun 30, 2020

To be clear, while the advice in the past was unarguably to use both, if the set of devices/software that are conceivably in use today forces a different best practice, I'm happy to update the recommendation in the airbnb config. However, I don't think there'd be anything actionable in this repo except perhaps updating the docs (so, I'll leave this open until we have a resolution).

In the meantime, and regardless of the outcome, this is an eslint rule - you can configure it to whatever you like :-)

@adamwathan
Copy link

adamwathan commented Jun 30, 2020

@corysimmons The information in this thread says that Dragon only supports for-ID linking, and that is what Tailwind UI uses. We haven't seen any evidence of a browser/device yet that does not support for-ID linking.

You made the claim that the Tailwind UI markup is not "a11y-friendly" because we use for-ID linking instead of nesting. We know that Dragon does support for-ID linking, in fact it only supports for-ID linking. Testing in Dragon will not validate what you're worried about because we already know the Tailwind UI mark up is perfectly fine in Dragon. It's the mystery "only supports nesting" devices we need to test in, and so far we have no idea what those devices are.

You said:

I think TailwindUI should default to nesting elements within labels.

We have zero evidence that this is required because so far no one has named any device that requires nesting. In fact so far we have only been able to name a tool (Dragon) that requires linking, which is what Tailwind UI does.

@jessebeach
Copy link
Collaborator

Folks can override the default AirBnB config for this rule in their local project, no?

@ljharb
Copy link
Member

ljharb commented Jul 5, 2020

Indeed they can, that's the beauty of eslint :-)

@aardrian
Copy link

Hey, I am the author of that vague/random tweet (and the blog post) mentioned above.

Dragon is voice dictation software, not a screen reader. For voice-only users, Dragon has been the de facto choice for years, even though its makers adamantly stress it is not AT (assistive technology).

I have worked with folks with motor impairments who rely on it, and it is a point of frustration for them as users. I have tested it, and it is still not recognized.

That being said, Dragon abandoned macOS, forcing Apple to build its own voice control support, and Windows has had it for years. More users are moving to the native options and, so far in testing, their support is... better? Factors which confuse testing include other issues on the page, and the mood of the winds (it really can be tough to nail down in testing), and how clearly the user speaks.

The good news is that as long as you are using native HTML controls (for the text fields, select menus, etc) then this is not a true barrier because a voice control user has other ways to get to them. But be aware that wrapping labels around fields can create a frustrating experience for some users in a very specific context.

My credentials are on my site in bio, but to save you the hassle I do accessibility consulting professionally and am happy to answer questions related to credibility, experience, favorite type of coffee, testing tools, and so on.

@adamwathan
Copy link

@aardrian Thank you! So reading between the lines a bit just to be absolutely clear, the recommendation is:

Use for and id linking, not wrapping

...correct? And are there any negative consequences you know of to using linking instead of wrapping? Any negative consequences to using both at the same time?

@aardrian
Copy link

Yeah, in short this construct:

<label for="FOO">Hey</label>
<input type="text" id="FOO">

Is safer than this construct:

<label>
    Hey
    <input type="text">
</label>

If your goal is to support the broadest possible number of users.

I would have to go back and test both at the same time as I recall there may have been a bug somewhere, but I think that is safe? Frankly, my memory goes back far enough I could be confusing it with the IE6 bug around wrapped labels as well.

For some confirmation, Accessibility Support is a handy resource and it talks about voice control (though the results are a year or more old).
https://a11ysupport.io/tech/html/label_element

I probably should have just linked that from the start instead of squeezing my ego.

@ljharb
Copy link
Member

ljharb commented Jul 16, 2020

@aardrian I'd be very interested to hear about any current downsides to using both.

@aardrian
Copy link

@ljharb I would as well. You can file a PR with https://a11ysupport.io/tech/html/label_element#related-tests and add a new test for when both are used together. Then if in the scope of testing you find something, we will all have it handy as a reference.

@axelboc

This comment has been minimized.

@ljharb

This comment has been minimized.

@axelboc

This comment has been minimized.

@aardrian
Copy link

This construct triggers a bug in Chrome:

<label>
 <input type="radio" […]>
 <span>Foo</span>
</label>

Ref:
FreedomScientific/VFO-standards-support#575

Chrome bug (fixed, not deployed):
https://bugs.chromium.org/p/chromium/issues/detail?id=1254723

@ljharb
Copy link
Member

ljharb commented Oct 13, 2021

@aardrian with the Chrome bug, what happens when the label also uses htmlFor and is linked to the input's ID?

@aardrian
Copy link

@ljharb I did not discover, report, nor test the bug. You could try the test case (adding the for attribute) and see what you get.

@manavm1990
Copy link

For ESLint configuration: jsx-a11y/label-has-associated-control: ["error", { assert: "either" } ]

@Yankovsky
Copy link

Could be because you don't have children inside label.

@Yankovsky
Copy link

And aria-label fixes the issue.

@aardrian
Copy link

@Yankovsky Using aria-label introduces a new SC 2.5.3 risk. It also does not auto-translate for most users. Which is part of why aria-label should be your last choice for providing an accessible name.

@Yankovsky
Copy link

@aardrian Interesting. Thanks for sharing.

In my case, I have a custom-style radio button, so the markup is something like this:

<input type='radio' style='visually hidden' id='my id'/>
<label for='my id' style='custom styles for beautiful radio' />

This radio can be used with some text label or without it as a part of more complex control. It seems that aria-label is the best solution in that case.

@aardrian
Copy link

It seems that aria-label is the best solution in that case.

Not sure I agree. No reason to dump visible text for a custom-styled radio. Refs:

Anyway, this is way outside the scope of this issue now.

@ljharb
Copy link
Member

ljharb commented Mar 31, 2023

@Yankovsky the best solution is still to put the input inside the label. It shouldn’t interfere with your styling.

@Yankovsky
Copy link

@ljharb Well, if you put the input inside the label, there is no way to make a custom-style radio with css only. You can check the articles provided by @aardrian in the previous message.
It is better to leave radios and checkboxes alone, but if you need a custom style for them, then using a sibling css selector is the way to go.

@ljharb
Copy link
Member

ljharb commented Apr 2, 2023

Then don’t do it with css only? (also I’m not convinced that’s true)

@jessebeach
Copy link
Collaborator

This rule is configurable and the conversation in the issue spells out considerations for the options. There is nothing to change in this project, as far as I can tell.

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

No branches or pull requests

8 participants