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

Improve accessibility of the checkbox/radio buttons plugin #14635

Closed
cvrebert opened this issue Sep 17, 2014 · 21 comments
Closed

Improve accessibility of the checkbox/radio buttons plugin #14635

cvrebert opened this issue Sep 17, 2014 · 21 comments
Milestone

Comments

@cvrebert
Copy link
Collaborator

See this blog post. I'm baffled as to why @danielnixon didn't file a bug about this.

@cvrebert cvrebert added this to the v3.2.1 milestone Sep 17, 2014
@cvrebert
Copy link
Collaborator Author

@mdo
Copy link
Member

mdo commented Sep 17, 2014

If you have a look at the DOM (or the implementation of button.js) you’ll notice that Bootstrap first hides the radio or checkbox input and then styles its label to appear visually like a button.

It was a creative solution to a problem: functional "radio" button groups. Folks wanted easy to use form-based components, but with the style of our buttons, so we gave it to them in an easy to implement way.

By this point I hope you’re as baffled as I am by Bootstrap’s apparent disinterest in basic accessibility techniques.

I'd caution @danielnixon and others to not assume malice or willful ignorance in these matters. We're a small team building a tool for millions of people. Mistakes and "bad implementations" are bound to happen.


I'm curious what we can do here. Is the solution radio buttons inside/outside the actual buttons? How do we keep sane markup without losing accessibility?

@cvrebert
Copy link
Collaborator Author

As he says in his post and does in his accessibility plugin fork, the existing markup can be made to work by adding some ARIA attributes.
As for what the optimal solution would be, assuming we could abandon the current markup, that seems to be an open question.

@alexlande
Copy link

That blog post is a little bit inaccurate/won't work as advertised. tabindex on label doesn't work in Chrome, Safari, or Opera, so you can't just add it and some JS and everything will work. I usually go with something like this:

http://jsbin.com/quyif/1/edit

With an adjacent sibling selector, you can style the visible part of the button based on the focus state of the input. Having to depend on DOM order like that is a bummer, but it works cross-browser and is pretty good. (Doing the same thing with the :checked selector is also ok, but doesn't work in IE8 so you need a JS fallback. Might as well just manage the behavior in JS with an .active class, really.)

A good thing to note is that you change the selected radio input with the arrow keys, not by tabbing and selecting the next one.

Don't know how difficult it would be to integrate something like that into Bootstrap.

@alexlande
Copy link

The current Bootstrap radio/checkbox buttons actually do work with keyboard input, you just can't see the focus styles because the input is focused, not the label. If you wanted it to work without markup changes you could apply a pseudo-focused class to the label.btn when the button is focused. That's a little gnarly too.

@danielnixon
Copy link
Contributor

@alexlande, in reply to your first comment, that sounds like a WebKit bug. Or are Firefox and IE doing something wrong by honoring tabindex on labels? In reply to your second comment, that wasn't the case when I created the PR/wrote that post; a commit to button.js added it some time between then and now.

@alexlande
Copy link

@danielnixon: Yeah, it's a webkit + blink bug. I did some research into this a while back and I think IE is the only browser that handles tabindex completely according to spec, which is pretty funny in a sad sort of way. I'll have to blog about it one of these days.

@cvrebert
Copy link
Collaborator Author

I'm personally in favor of the :checked + sibling selector option, as it avoids any issues with the visual checkedness getting out of sync with the <input>'s actual checkedness when folks need to programmatically change the checkedness.

@alexlande
Copy link

@cvrebert: Would it be worthwhile for me to open a PR to see what that might look like?

@cvrebert
Copy link
Collaborator Author

@alexlande Eh, we're already planning to look at it for v4 (and definitely not for v3), which is still a little ways off, so I wouldn't bother. Appreciate the enthusiasm though.

@alexlande
Copy link

👍

@mdo
Copy link
Member

mdo commented Oct 1, 2014

So what needs doing here exactly for v3.2.1? We can't use the :checked and sibling selector option until v4 as it changes the required DOM order (radio button outside button element rather than within it.

@cvrebert
Copy link
Collaborator Author

cvrebert commented Oct 1, 2014

  • Add tabindex="0" and role="button" to the <label>s
  • Add aria-pressed="false" to the <label>s and add JS to toggle it
  • Add JS to handle spacebar(/Enter key?) keyboard events and toggle the checkedness

@alexlande
Copy link

I don't think that will work (see previous comments). Webkit + Blink don't support tabindex on label, and adding ARIA roles and keyboard listeners is just mixing up the semantics. The current implementation is pretty screen reader friendly, the issue is that keyboard users can't see which input elements are focused. Since the required markup can't change, you could do something like this:

$btnGroupInputs.on("focus", function () {
  $(this).parent(".btn").addClass(".focused");
}).on("blur", function () {
  $(this).parent(".btn").removeClass(".focused");
});

In which the .focused class would give the .btn :focus styles.

@mdo
Copy link
Member

mdo commented Oct 1, 2014

Oh, we have the .focused stuff coming in v3.2.1 already I believe.

@hnrch02
Copy link
Collaborator

hnrch02 commented Oct 1, 2014

Yeah, see #13907.

@alexlande
Copy link

Nice! In that case you should be in good shape.

@mdo
Copy link
Member

mdo commented Oct 1, 2014

Closing out then.

@mdo mdo closed this as completed Oct 1, 2014
@danielnixon
Copy link
Contributor

This means visual users will see buttons but non-visual users will get check boxes (or radio buttons), doesn't it? If so, I think that's still problematic. Consider a scenario where a vision-impaired user is working with a non-vision-impaired user on the same page (maybe they're collaborating on the same physical computer, or maybe it's a desktop sharing type scenario, or maybe it's a tech support phone call). The conversation could go something like this (or the inverse):

A: "Alright, now check the foo check box".
B: "What are you talking about? There are only buttons on this page."

@alexlande
Copy link

That's a fair concern. What do you think a good solution for it is? I'm kind of at a loss.

Thierry Koblentz wrote an article + demo recently with a similar technique, and my feeling at the time was that it validated this kind of usage, a11y-wise.

Seems like a slippery slope to attempt to make a page read that similarly for sighted and non-sighted users (rather than just making it work well for both groups), but maybe I'm off-base.

@patrickhlauke
Copy link
Member

personally, i think the "sighted and non-sighted user working together" scenario is a rather edge-case one. also, assuming the checkbox has a logically-named label, the conversation would be "tick the 'chicken' checkbox", "i don't see a checkbox, but there's something that looks like a toggle button labelled 'chicken', do you mean that?"

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

No branches or pull requests

6 participants