|
6 | 6 |
|
7 | 7 | # Accessibility with ngAria
|
8 | 8 |
|
9 |
| -You can use the `ngAria` module to have common ARIA attributes automatically applied when you |
10 |
| -use certain directives. To enable `ngAria`, just require the module into your application and |
11 |
| -the code will hook into your ng-show/ng-hide, input, textarea, button, select and |
12 |
| -ng-required directives and add the appropriate ARIA states and properties. |
| 9 | +The goal of ngAria is to improve Angular's default accessibility by enabling common |
| 10 | +[ARIA](http://www.w3.org/TR/wai-aria/) attributes that convey state or semantic information for |
| 11 | +assistive technologies used by persons with disabilities. |
| 12 | + |
| 13 | +##Including ngAria |
| 14 | + |
| 15 | +Using ngAria is as simple as requiring the ngAria module in your application. ngAria hooks into |
| 16 | +standard AngularJS directives and quietly injects accessibility support into your application |
| 17 | +at runtime. |
| 18 | + |
| 19 | +```js |
| 20 | +angular.module('myApp', ['ngAria'])... |
| 21 | +``` |
| 22 | + |
| 23 | +Currently, ngAria interfaces with the following directives: |
| 24 | + |
| 25 | + * <a href="#ngmodel">ngModel</a> |
| 26 | + * <a href="#ngdisabled">ngDisabled</a> |
| 27 | + * <a href="#ngshow">ngShow</a> |
| 28 | + * <a href="#nghide">ngHide</a> |
| 29 | + * <a href="#ngclick-and-ngdblclick">ngClick</a> |
| 30 | + * <a href="#ngclick-and-ngdblclick">ngDblClick</a> |
| 31 | + |
| 32 | +<h2 id="ngmodel">ngModel</h2> |
| 33 | + |
| 34 | +Most of ngAria's heavy lifting happens in the [ngModel](https://docs.angularjs.org/api/ng/directive/ngModel) |
| 35 | +directive. For elements using ngModel, special attention is paid by ngAria if that element also |
| 36 | +has a a role or type of `checkbox`, `radio`, `range` or `textbox`. |
| 37 | + |
| 38 | +For those elements using ngModel, ngAria will dynamically bind and update the following ARIA |
| 39 | +attributes (if they have not been explicitly specified by the developer): |
13 | 40 |
|
14 |
| -Currently, the following attributes are implemented: |
15 |
| - * aria-hidden |
16 | 41 | * aria-checked
|
17 |
| - * aria-disabled |
18 |
| - * aria-required |
19 |
| - * aria-invalid |
20 |
| - * aria-multiline |
21 |
| - * aria-valuenow |
22 | 42 | * aria-valuemin
|
23 | 43 | * aria-valuemax
|
24 |
| - * tabindex |
25 |
| - |
26 |
| -You can disable individual attributes by using the `{@link ngAria.$ariaProvider#config config}` method. |
| 44 | + * aria-valuenow |
| 45 | + * aria-invalid |
| 46 | + * aria-required |
27 | 47 |
|
28 | 48 | ###Example
|
29 | 49 |
|
30 |
| -```js |
31 |
| -angular.module('myApp', ['ngAria'])... |
| 50 | +```html |
| 51 | +<md-checkbox ng-model="val" required> |
32 | 52 | ```
|
33 | 53 |
|
34 |
| -Elements using `ng-model` with `required` or `ngRequired` directives will automatically have |
35 |
| -`aria-required` attributes with the proper corresponding values. |
| 54 | +Becomes: |
36 | 55 |
|
37 | 56 | ```html
|
38 |
| -<material-input ng-model="val" required> |
| 57 | +<md-checkbox ng-model="val" required aria-required="true" tabIndex="0"> |
| 58 | +``` |
| 59 | + |
| 60 | +ngAria will also add `tabIndex`, ensuring custom elements with these roles will be reachable from |
| 61 | +the keyboard. It is still up to **you** as a developer to **ensure custom controls will be |
| 62 | +operable** from the keybard. Think of `ng-click` on a `<div>` or `<md-checkbox>`: you still need |
| 63 | +to bind `ng-keypress` to make it fully operable from the keyboard. As a rule, any time you create |
| 64 | +a widget involving user interaction, be sure to test it with your keyboard and at least one mobile |
| 65 | +and desktop screen reader (preferably more). |
| 66 | + |
| 67 | +<h2 id="ngdisabled">ngDisabled</h2> |
| 68 | + |
| 69 | +The `disabled` attribute is only valid for certain elements such as `button`, `input` and |
| 70 | +`textarea`. To properly disable custom element directives such as `<md-checkbox>` or `<taco-tab>`, |
| 71 | +using ngAria with [ngDisabled](https://docs.angularjs.org/api/ng/directive/ngDisabled) will also |
| 72 | +add `aria-disabled`. This tells assistive technologies when a non-native input is disabled, helping |
| 73 | +custom controls to be more accessible. |
| 74 | + |
| 75 | +###Example |
| 76 | + |
| 77 | +```html |
| 78 | +<md-checkbox ng-disabled="disabled"> |
39 | 79 | ```
|
40 | 80 |
|
41 | 81 | Becomes:
|
42 | 82 |
|
43 | 83 | ```html
|
44 |
| -<material-input ng-model="val" required aria-required="true"> |
| 84 | +<md-checkbox disabled aria-disabled="true"> |
45 | 85 | ```
|
46 | 86 |
|
47 |
| -ngAria is just a starting point. You'll have to manually choose how to implement some |
48 |
| -accessibility features. |
| 87 | +>You can check whether a control is legitimately disabled for a screen reader by visiting |
| 88 | +[chrome://accessibility](chrome://accessibility). |
49 | 89 |
|
50 |
| -For instance, you may want to add `ng-keypress` bindings alongside `ng-click` to make keyboard |
51 |
| -navigation easier. |
| 90 | +<h2 id="ngshow">ngShow</h2> |
52 | 91 |
|
| 92 | +>The [ngShow](https://docs.angularjs.org/api/ng/directive/ngShow) directive shows or hides the |
| 93 | +given HTML element based on the expression provided to the `ngShow` attribute. The element is |
| 94 | +shown or hidden by removing or adding the `.ng-hide` CSS class onto the element. |
53 | 95 |
|
54 |
| -## Additional Resources |
| 96 | +In its default setup, ngAria for `ngShow` is actually redundant. It toggles `aria-hidden` on the |
| 97 | +directive when it is hidden or shown. However, the default CSS of `display: none !important`, |
| 98 | +already hides child elements from a screen reader. It becomes more useful when the default |
| 99 | +CSS is overridden with properties that don’t affect assistive technologies, such as `opacity` |
| 100 | +or `transform`. By toggling `aria-hidden` dynamically with ngAria, we can ensure content visually |
| 101 | +hidden with this technique will not be read aloud in a screen reader. |
| 102 | + |
| 103 | +One caveat with this combination of CSS and `aria-hidden`: you must also remove links and other |
| 104 | +interactive child elements from the tab order using `tabIndex=“-1”` on each control. This ensures |
| 105 | +screen reader users won't accidentally focus on "mystery elements". Managing tab index on every |
| 106 | +child control can be complex and affect performance, so it’s best to just stick with the default |
| 107 | +`display: none` CSS. See the [fourth rule of ARIA use](http://www.w3.org/TR/aria-in-html/#fourth-rule-of-aria-use). |
| 108 | + |
| 109 | +<h2 id="nghide">ngHide</h2> |
| 110 | + |
| 111 | +>The [ngHide](https://docs.angularjs.org/api/ng/directive/ngHide) directive shows or hides the |
| 112 | +given HTML element based on the expression provided to the `ngHide` attribute. The element is |
| 113 | +shown or hidden by removing or adding the `.ng-hide` CSS class onto the element. |
| 114 | + |
| 115 | +The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redundant. It toggles |
| 116 | +`aria-hidden` on the directive when it is hidden or shown, but the content is already hidden with |
| 117 | +`display: none`. See explanation for <a href="#ngshow">ngShow</a> when overriding the default CSS. |
| 118 | + |
| 119 | +<h2 id="ngclick">ngClick and ngDblClick</h2> |
| 120 | +If `ngClick` or `ngDblClick` is encountered, ngAria will add `tabIndex` if it isn't there already. |
| 121 | +Even with this, you must currently still add `ng-keypress` to non-interactive elements such as |
| 122 | +`<div>` or `<taco-button>` to enable keyboard access. I have recommended this also bind |
| 123 | +`ng-keypress` to be more useful; the conversation is [currently ongoing](https://github.com/angular/angular.js/issues/9254). |
| 124 | + |
| 125 | +* * * |
| 126 | + |
| 127 | +##Disabling attributes |
| 128 | +The attribute magic of ngAria may not work for every scenario. To disable individual attributes, |
| 129 | +you can use the `{@link ngAria.$ariaProvider#config config}` method: |
| 130 | + |
| 131 | +``` |
| 132 | +angular.module('myApp', ['ngAria'], function config($ariaProvider) { |
| 133 | + $ariaProvider.config({ |
| 134 | + tabindex: false |
| 135 | + }); |
| 136 | +}); |
| 137 | +``` |
| 138 | +* * * |
| 139 | + |
| 140 | +##Common Accessibility Patterns |
55 | 141 |
|
56 | 142 | Accessibility best practices that apply to web apps in general also apply to Angular.
|
57 | 143 |
|
58 |
| -* [A11Y Project](http://a11yproject.com/) |
59 |
| -* [WebAim](http://webaim.org/) |
60 |
| -* [Using WAI-ARIA in HTML](http://www.w3.org/TR/2014/WD-aria-in-html-20140626/) |
61 |
| -* [Apps For All: Coding Accessible Web Applications](https://shop.smashingmagazine.com/apps-for-all-coding-accessible-web-applications.html) |
| 144 | + * **Text alternatives**: Add alternate text content to make visual information accessible using |
| 145 | + [these W3C guidelines](http://www.w3.org/TR/html-alt-techniques/). The appropriate technique |
| 146 | + depends on the specific markup but can be accomplished using offscreen spans, `aria-label` or |
| 147 | + label elements, image `alt` attributes, `figure`/`figcaption` elements and more. |
| 148 | + * **HTML Semantics**: If you're creating custom element directives, Web Components or HTML in |
| 149 | + general, use native elements wherever possible to utilize built-in events and properties. |
| 150 | + Alternatively, use ARIA to communicate semantic meaning. See [notes on ARIA use](http://www.w3.org/TR/aria-in-html/#notes-on-aria-use-in-html). |
| 151 | + * **Focus management**: Guide the user around the app as views are appended/removed. |
| 152 | + Focus should *never* be lost, as this causes unexpected behavior and much confusion (referred to |
| 153 | + as "freak-out mode"). |
| 154 | + * **Announcing changes**: When filtering or other UI messaging happens away from the user's focus, |
| 155 | + notify with [ARIA Live Regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions). |
| 156 | + * **Color contrast and scale**: Make sure content is legible and interactive controls are usable |
| 157 | + at all screen sizes. Consider configurable UI themes for people with color blindness, low vision |
| 158 | + or other visual impairments. |
| 159 | + * **Progressive enhancement**: Some users do not browse with JavaScript enabled or do not have |
| 160 | + the latest browser. An accessible message about site requirements can inform users and improve |
| 161 | + the experience. |
| 162 | + |
| 163 | +## Additional Resources |
| 164 | + |
| 165 | + * [Using ARIA in HTML](http://www.w3.org/TR/aria-in-html/) |
| 166 | + * [AngularJS Accessibility at ngEurope](https://www.youtube.com/watch?v=dmYDggEgU-s&list=UUEGUP3TJJfMsEM_1y8iviSQ) |
| 167 | + * [Chrome Accessibility Developer Tools](https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb?hl=en) |
| 168 | + * [W3C Accessibility Testing](http://www.w3.org/wiki/Accessibility_testing) |
| 169 | + * [WebAIM](http://webaim.org) |
| 170 | + * [A11y Project](http://a11yproject.com) |
0 commit comments