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

Accessibility feedback #20737

Closed
BootstrapAccessilibty opened this issue Sep 17, 2016 · 6 comments
Closed

Accessibility feedback #20737

BootstrapAccessilibty opened this issue Sep 17, 2016 · 6 comments
Assignees

Comments

@BootstrapAccessilibty
Copy link

BootstrapAccessilibty commented Sep 17, 2016

Here are the semantics issues

Links with the button role

<a class="btn btn-default" href="#" role="button">Link</a>

Mozilla Developer Network(MDN)

Warning: Be careful when marking up links with the button role. Buttons are expected to be triggered using the Space key, while links are expected to be triggered using the Enter key. In other words, when links are used to behave like buttons, adding role="button" alone is not sufficient. It will also be necessary to add a key event handler that listens for the Space key in order to be consistent with native buttons.

Using ARIA attributes when there is a native html way

In W3C document, you will find First rule of ARIA use:
If you can use a native HTML element [HTML5] or attribute with the semantics and behaviour you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.

For example:

aria-describedby for the help text or error message

<label class="control-label" for="inputError2">Input with error</label>
<input type="text" class="form-control" id="inputError2" aria-describedby="inputError2Status">
<span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>
<span id="inputError2Status" class="sr-only">(error)</span>

The correct way should append error message after label without using aria-describedby tag

<label class="control-label" for="inputError2">
    Input with error 
   <span class="sr-only">(error)</span>
</label>
<input type="text" class="form-control" id="inputError2">
<span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>

aria-label for Checkboxes and radios without label

<div class="checkbox">
  <label>
    <input type="checkbox" id="blankCheckbox" value="option1" aria-label="...">
  </label>
</div>

The correct way should be :

<div class="checkbox">
  <label>
    <input type="checkbox" id="blankCheckbox" value="option1">
    <span class="sr-only">label text</span>
  </label>
</div>

So much other places:
http://getbootstrap.com/components/#pagination-default
http://getbootstrap.com/components/#disabled-and-active-states
http://getbootstrap.com/components/#glyphicons-examples
http://getbootstrap.com/components/#btn-groups-toolbar

Input without label

http://getbootstrap.com/css/#selects

http://getbootstrap.com/css/#textarea

http://getbootstrap.com/css/#inputs

Dropdown should be replaced with select

Based on First rule of ARIA use, it can use select (html native) to achieve same goal

A tag with href="#"

A tag with href="#" should be replace with button. Please look at When To Use The Button Element

For example:

Tabs

Semantically A tag should be replaced with button

<ul class="nav nav-tabs">
  <li role="presentation" class="active"><a href="#">Home</a></li>
  <li role="presentation"><a href="#">Profile</a></li>
  <li role="presentation"><a href="#">Messages</a></li>
</ul>

Should be

<ul class="nav nav-tabs">
  <li role="presentation" class="active"><button>Home</button></li>
  <li role="presentation"><button>Profile</button></li>
  <li role="presentation"><button>Messages</button></li>
</ul>

Tabs with dropdowns

Based on First rule of ARIA use, it should use button directly without marking up links with the role="button".

<ul class="nav nav-tabs">
  ...
  <li role="presentation" class="dropdown">
    <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
      Dropdown <span class="caret"></span>
    </a>
    <ul class="dropdown-menu">
      ...
    </ul>
  </li>
  ...
</ul>

Should be

<ul class="nav nav-tabs">
  ...
  <li role="presentation" class="dropdown">
    <button class="dropdown-toggle" data-toggle="dropdown"  aria-haspopup="true" aria-expanded="false">
      Dropdown <span class="caret"></span>
    </button>
    <ul class="dropdown-menu">
      ...
    </ul>
  </li>
  ...
</ul>

Linked items

<div class="list-group">
  <a href="#" class="list-group-item active">
    Cras justo odio
  </a>
  <a href="#" class="list-group-item">Dapibus ac facilisis in</a>
  <a href="#" class="list-group-item">Morbi leo risus</a>
  <a href="#" class="list-group-item">Porta ac consectetur ac</a>
  <a href="#" class="list-group-item">Vestibulum at eros</a>
</div>

Should be

<div class="list-group">
  <button class="list-group-item active">
    Cras justo odio
  </button >
  <button class="list-group-item">Dapibus ac facilisis in</button>
  <button class="list-group-item">Morbi leo risus</a>
  <button class="list-group-item">Porta ac consectetur ac</button>
  <button class="list-group-item">Vestibulum at eros</button>
</div>

Here are the issues in the javaScript:

modal

When using NVDA and ChromeVox, user cannot use up/down array key to read modal content, when it has role="dialog" and role="document"

Accordion

Based on First rule of ARIA use, it should use button directly without marking up links with the role="button".

 <div class="panel-heading" role="tab" id="headingThree">
      <h4 class="panel-title">
        <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
          Collapsible Group Item #3
        </a>
      </h4>
</div>

should be

 <div class="panel-heading" role="tab" id="headingThree">
      <h4 class="panel-title">
        <button class="collapsed" data-toggle="collapse" data-parent="#accordion"  aria-expanded="false" aria-controls="collapseThree">
          Collapsible Group Item #3
        </a>
      </h4>
</div>

tabs

Keyboard Interaction is not implemented. For example user cannot use left/right or up/down array keys to switch between tabs.

Please refer to https://www.w3.org/TR/wai-aria-practices-1.1/#tabpanel

@rafalp
Copy link

rafalp commented Sep 17, 2016

Very nice writeup, but I think its at least partially erronous. The href="#" bits seem to come from ill-informed basis. Its an example markup. In implementation you'll replace that hash with your app's urls, so saying those should be buttons isn't really valid.

@pkozlowski-opensource
Copy link

Ha! Thnx for the write-up @BootstrapAccessilibty and initial comment @rafalp - in fact we've debated this link vs. button accessibility issue to (near) death in the https://ng-bootstrap.github.io (Bootstrap 4 integration for Angular 2). You can see the details here: ng-bootstrap/ng-bootstrap#142

In implementation you'll replace that hash with your app's urls. So saying those should be buttons isn't really valid.

It might depend on an application. In the context os SPAs many of the constructs that are links today (ex. pages in pagination, menu items id a dropdown, tab / accordion headers etc.) are not real links (that is, they don't change the page). Rather clicking on those invoke an action (go to a different page, execute a command from a menu etc.).

In any case <a href="#"> are problematic for SPAs + routers. On the https://ng-bootstrap.github.io we are using half-baked work-arrounds:

  • sometimes using buttons
  • sometimes using <a href ...> with preventDefault()

As far as I understand both of those solutions are far from ideal (buttons can't be used in all places where <a> is used today due to styling and <a href ...> + preventDefault() is pure hack...).

Unfortunately I'm not an accessibility expert so not sure what the best / final solution is going to be but I'm happy that the discussion is happening here 👍

@wolfy1339
Copy link
Contributor

I believe that v4 should address some of these problems.
Anyways, v3 is no longer maintained and so these issues will not get fixed. (exept for the occasionnal bugfix) They have put v4 on the front burner to try and focus more development on it

@pkozlowski-opensource
Copy link

Anyways, v3 is no longer maintained and so these issues will not get fixed. (exept for the occasionnal bugfix) They have put v4 on the front burner to try and focus more development on it

As of today many (most?) of those issues are still in the v4 branch so I don't think it is v3 specific.

I believe that v4 should address some of these problems.

Do you have concrete examples?

@patrickhlauke
Copy link
Member

Interesting write-up, but most of it based on your opinion I'm afraid.

  • links with button role: we already stress a few times that authors should really be using <button>. adding a reminder for them to add JS key handling as well as the role is a good suggestion though

for the various "first rule of ARIA" - be careful not to naively interpret this as if it was indeed an absolute rule. Accessibility is about the end result, the user experience for users with disabilities, and there are always multiple ways to achieve the same thing. In many cases, compromises have to be made on which exact method to use (particularly in frameworks that are very high-level and allow users to build all sorts of sites/interfaces, as is the case with Bootstrap), but if the end result is the same (i.e. what a browser exposes via the accessibility API to AT), it comes down to personal preference HOW exactly the markup is structured, and whether it uses one particular patterns over another.

The correct way should append error message after label without using aria-describedby tag

according to which authority, please? no, the construct used with aria-describedby is perfectly valid and well supported.

aria-label for Checkboxes and radios without label

perfectly valid, again

Input without label

clearly those are examples in the documentation itself, not examples of what we'd expect users to implement. fair enough, the example codes could be provided with some generic labels.

Dropdown should be replaced with select

clearly no, as the dropdown contains links. or are you then suggesting adding onchange handlers, or even a "Go" button?

A tag with href="#"

those are from examples for a site. they're dummy links to show how your proper navigation to different pages would look.

Linked items

some as above, these are just dummy links...authors would then change those to links to pages on their site, or whatever.

Modal

modals are problematic, as true dialogs are not meant to have any content that is read with reading keys; the way bootstrap modals are used in the wild suggests we may actually want to drop the role="dialog" altogether, as this sets certain AT (namely NVDA) into essentially forms mode.

tabs

this was a conscious decision, as for websites (rather than applications), non-AT keyboard users don't generally expect to use cursor keys. we're considering doing a half-way implementation

@mdo mdo changed the title I found bootstrap semantics pretty appalling and the css incredibly bloated Accessibility feedback Sep 18, 2016
@mdo
Copy link
Member

mdo commented Oct 9, 2016

Closing for now given the lack of todos here based on @patrickhlauke's comment. Feel free to open new, more specific issues if there is something here to follow up on though.

@mdo mdo closed this as completed Oct 9, 2016
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