"Fossies" - the Fresh Open Source Software Archive

Member "angular-1.8.2/docs/partials/guide/accessibility.html" (21 Oct 2020, 21793 Bytes) of package /linux/www/angular-1.8.2.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) HTML source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 <a href='https://github.com/angular/angular.js/edit/v1.8.x/docs/content/guide/accessibility.ngdoc?message=docs(guide%2FAccessibility)%3A%20describe%20your%20change...' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this Doc</a>
    2 
    3 
    4 <h1 id="accessibility-with-ngaria">Accessibility with ngAria</h1>
    5 <p>The goal of ngAria is to improve AngularJS&#39;s default accessibility by enabling common
    6 <a href="http://www.w3.org/TR/wai-aria/">ARIA</a> attributes that convey state or semantic information for
    7 assistive technologies used by persons with disabilities.</p>
    8 <h2 id="including-ngaria">Including ngAria</h2>
    9 <p>Using <a href="api/ngAria">ngAria</a> is as simple as requiring the ngAria module in your application. ngAria hooks into
   10 standard AngularJS directives and quietly injects accessibility support into your application
   11 at runtime.</p>
   12 <pre><code class="lang-js">angular.module(&#39;myApp&#39;, [&#39;ngAria&#39;])...
   13 </code></pre>
   14 <h3 id="using-ngaria">Using ngAria</h3>
   15 <p>Most of what ngAria does is only visible &quot;under the hood&quot;. To see the module in action, once you&#39;ve
   16 added it as a dependency, you can test a few things:</p>
   17 <ul>
   18 <li>Using your favorite element inspector, look for attributes added by ngAria in your own code.</li>
   19 <li>Test using your keyboard to ensure <code>tabindex</code> is used correctly.</li>
   20 <li>Fire up a screen reader such as VoiceOver or NVDA to check for ARIA support.
   21 <a href="http://webaim.org/articles/screenreader_testing/">Helpful screen reader tips.</a></li>
   22 </ul>
   23 <h2 id="supported-directives">Supported directives</h2>
   24 <p>Currently, ngAria interfaces with the following directives:</p>
   25 <ul>
   26 <li><a href="guide/accessibility#ngmodel">ngModel</a></li>
   27 <li><a href="guide/accessibility#ngdisabled">ngDisabled</a></li>
   28 <li><a href="guide/accessibility#ngrequired">ngRequired</a></li>
   29 <li><a href="guide/accessibility#ngreadonly">ngReadonly</a></li>
   30 <li><a href="guide/accessibility#ngvaluechecked">ngChecked</a></li>
   31 <li><a href="guide/accessibility#ngvaluechecked">ngValue</a></li>
   32 <li><a href="guide/accessibility#ngshow">ngShow</a></li>
   33 <li><a href="guide/accessibility#nghide">ngHide</a></li>
   34 <li><a href="guide/accessibility#ngclick">ngClick</a></li>
   35 <li><a href="guide/accessibility#ngdblclick">ngDblClick</a></li>
   36 <li><a href="guide/accessibility#ngmessages">ngMessages</a></li>
   37 </ul>
   38 <h2 id="ngmodel">ngModel</h2>
   39 
   40 <p>Much of ngAria&#39;s heavy lifting happens in the <a href="api/ng/directive/ngModel">ngModel</a>
   41 directive. For elements using ngModel, special attention is paid by ngAria if that element also
   42 has a role or type of <code>checkbox</code>, <code>radio</code>, <code>range</code> or <code>textbox</code>.</p>
   43 <p>For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
   44 attributes (if they have not been explicitly specified by the developer):</p>
   45 <ul>
   46 <li>aria-checked</li>
   47 <li>aria-valuemin</li>
   48 <li>aria-valuemax</li>
   49 <li>aria-valuenow</li>
   50 <li>aria-invalid</li>
   51 <li>aria-required</li>
   52 <li>aria-readonly</li>
   53 <li>aria-disabled</li>
   54 </ul>
   55 <h3 id="example">Example</h3>
   56 <p>
   57 
   58 <div>
   59   <plnkr-opener example-path="examples/example-accessibility-ng-model"></plnkr-opener>
   60 
   61   <div class="runnable-example"
   62       path="examples/example-accessibility-ng-model"
   63       module="ngAria_ngModelExample"
   64       deps="angular-aria.js"
   65       name="accessibility-ng-model">
   66 
   67   
   68     <div class="runnable-example-file" 
   69       name="index.html"
   70       language="html"
   71       type="html">
   72       <pre><code>&lt;form&gt;&#10;  &lt;custom-checkbox role=&quot;checkbox&quot; ng-model=&quot;checked&quot; required&#10;      aria-label=&quot;Custom checkbox&quot; show-attrs&gt;&#10;    Custom checkbox&#10;  &lt;/custom-checkbox&gt;&#10;&lt;/form&gt;&#10;&lt;hr /&gt;&#10;&lt;b&gt;Is checked:&lt;/b&gt; {{ !!checked }}</code></pre>
   73     </div>
   74   
   75     <div class="runnable-example-file" 
   76       name="script.js"
   77       language="js"
   78       type="js">
   79       <pre><code>angular.&#10;  module(&#39;ngAria_ngModelExample&#39;, [&#39;ngAria&#39;]).&#10;  directive(&#39;customCheckbox&#39;, customCheckboxDirective).&#10;  directive(&#39;showAttrs&#39;, showAttrsDirective);&#10;&#10;function customCheckboxDirective() {&#10;  return {&#10;    restrict: &#39;E&#39;,&#10;    require: &#39;ngModel&#39;,&#10;    transclude: true,&#10;    template:&#10;        &#39;&lt;span class=&quot;icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt; &#39; +&#10;        &#39;&lt;ng-transclude&gt;&lt;/ng-transclude&gt;&#39;,&#10;    link: function(scope, elem, attrs, ctrl) {&#10;      // Overwrite necessary `NgModelController` methods&#10;      ctrl.$isEmpty = isEmpty;&#10;      ctrl.$render = render;&#10;&#10;      // Bind to events&#10;      elem.on(&#39;click&#39;, function(event) {&#10;        event.preventDefault();&#10;        scope.$apply(toggleCheckbox);&#10;      });&#10;      elem.on(&#39;keypress&#39;, function(event) {&#10;        event.preventDefault();&#10;        if (event.keyCode === 32 || event.keyCode === 13) {&#10;          scope.$apply(toggleCheckbox);&#10;        }&#10;      });&#10;&#10;      // Helpers&#10;      function isEmpty(value) {&#10;        return !value;&#10;      }&#10;&#10;      function render() {&#10;        elem[ctrl.$viewValue ? &#39;addClass&#39; : &#39;removeClass&#39;](&#39;checked&#39;);&#10;      }&#10;&#10;      function toggleCheckbox() {&#10;        ctrl.$setViewValue(!ctrl.$viewValue);&#10;        ctrl.$render();&#10;      }&#10;    }&#10;  };&#10;}&#10;&#10;function showAttrsDirective($timeout) {&#10;  return function(scope, elem, attrs) {&#10;    var pre = document.createElement(&#39;pre&#39;);&#10;    elem.after(pre);&#10;&#10;    scope.$watchCollection(function() {&#10;      return Array.prototype.slice.call(elem[0].attributes).reduce(function(aggr, attr) {&#10;        if (attr.name !== attrs.$attr.showAttrs) aggr[attr.name] = attr.value;&#10;        return aggr;&#10;      }, {});&#10;    }, function(newValues) {&#10;      $timeout(function() {&#10;        pre.textContent = angular.toJson(newValues, 2);&#10;      });&#10;    });&#10;  };&#10;}</code></pre>
   80     </div>
   81   
   82     <div class="runnable-example-file" 
   83       name="style.css"
   84       language="css"
   85       type="css">
   86       <pre><code>custom-checkbox {&#10;  cursor: pointer;&#10;  display: inline-block;&#10;}&#10;&#10;custom-checkbox .icon:before {&#10;  content: &#39;\2610&#39;;&#10;  display: inline-block;&#10;  font-size: 2em;&#10;  line-height: 1;&#10;  speak: none;&#10;  vertical-align: middle;&#10;}&#10;&#10;custom-checkbox.checked .icon:before {&#10;  content: &#39;\2611&#39;;&#10;}</code></pre>
   87     </div>
   88   
   89     <div class="runnable-example-file" 
   90       name="protractor.js"
   91       type="protractor"
   92       language="js">
   93       <pre><code>var checkbox = element(by.css(&#39;custom-checkbox&#39;));&#10;var checkedCheckbox = element(by.css(&#39;custom-checkbox.checked&#39;));&#10;&#10;it(&#39;should have the `checked` class only when checked&#39;, function() {&#10;  expect(checkbox.isPresent()).toBe(true);&#10;  expect(checkedCheckbox.isPresent()).toBe(false);&#10;&#10;  checkbox.click();&#10;  expect(checkedCheckbox.isPresent()).toBe(true);&#10;&#10;  checkbox.click();&#10;  expect(checkedCheckbox.isPresent()).toBe(false);&#10;});&#10;&#10;it(&#39;should have the `aria-checked` attribute set to the appropriate value&#39;, function() {&#10;  expect(checkedCheckbox.isPresent()).toBe(false);&#10;  expect(checkbox.getAttribute(&#39;aria-checked&#39;)).toBe(&#39;false&#39;);&#10;&#10;  checkbox.click();&#10;  expect(checkedCheckbox.isPresent()).toBe(true);&#10;  expect(checkbox.getAttribute(&#39;aria-checked&#39;)).toBe(&#39;true&#39;);&#10;&#10;  checkbox.click();&#10;  expect(checkedCheckbox.isPresent()).toBe(false);&#10;  expect(checkbox.getAttribute(&#39;aria-checked&#39;)).toBe(&#39;false&#39;);&#10;});</code></pre>
   94     </div>
   95   
   96 
   97     <iframe class="runnable-example-frame" src="examples/example-accessibility-ng-model/index.html" name="example-accessibility-ng-model"></iframe>
   98   </div>
   99 </div>
  100 
  101 
  102 </p>
  103 <p>ngAria will also add <code>tabIndex</code>, ensuring custom elements with these roles will be reachable from
  104 the keyboard. It is still up to <strong>you</strong> as a developer to <strong>ensure custom controls will be
  105 accessible</strong>. As a rule, any time you create a widget involving user interaction, be sure to test
  106 it with your keyboard and at least one mobile and desktop screen reader.</p>
  107 <h2 id="ngvaluechecked">ngValue and ngChecked</h2>
  108 
  109 <p>To ease the transition between native inputs and custom controls, ngAria now supports
  110 <a href="api/ng/directive/ngValue">ngValue</a> and <a href="api/ng/directive/ngChecked">ngChecked</a>.
  111 The original directives were created for native inputs only, so ngAria extends
  112 support to custom elements by managing <code>aria-checked</code> for accessibility.</p>
  113 <h3 id="example">Example</h3>
  114 <pre><code class="lang-html">&lt;custom-checkbox ng-checked=&quot;val&quot;&gt;&lt;/custom-checkbox&gt;
  115 &lt;custom-radio-button ng-value=&quot;val&quot;&gt;&lt;/custom-radio-button&gt;
  116 </code></pre>
  117 <p>Becomes:</p>
  118 <pre><code class="lang-html">&lt;custom-checkbox ng-checked=&quot;val&quot; aria-checked=&quot;true&quot;&gt;&lt;/custom-checkbox&gt;
  119 &lt;custom-radio-button ng-value=&quot;val&quot; aria-checked=&quot;true&quot;&gt;&lt;/custom-radio-button&gt;
  120 </code></pre>
  121 <h2 id="ngdisabled">ngDisabled</h2>
  122 
  123 <p>The <code>disabled</code> attribute is only valid for certain elements such as <code>button</code>, <code>input</code> and
  124 <code>textarea</code>. To properly disable custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;taco-tab&gt;</code>,
  125 using ngAria with <a href="api/ng/directive/ngDisabled">ngDisabled</a> will also
  126 add <code>aria-disabled</code>. This tells assistive technologies when a non-native input is disabled, helping
  127 custom controls to be more accessible.</p>
  128 <h3 id="example">Example</h3>
  129 <pre><code class="lang-html">&lt;md-checkbox ng-disabled=&quot;disabled&quot;&gt;&lt;/md-checkbox&gt;
  130 </code></pre>
  131 <p>Becomes:</p>
  132 <pre><code class="lang-html">&lt;md-checkbox disabled aria-disabled=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
  133 </code></pre>
  134 <div class="alert alert-info">
  135 You can check whether a control is legitimately disabled for a screen reader by visiting
  136 <a href="chrome://accessibility">chrome://accessibility</a> and inspecting <a href="http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/">the accessibility tree</a>.
  137 </div>
  138 
  139 <h2 id="ngrequired">ngRequired</h2>
  140 
  141 <p>The boolean <code>required</code> attribute is only valid for native form controls such as <code>input</code> and
  142 <code>textarea</code>. To properly indicate custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;custom-input&gt;</code>
  143 as required, using ngAria with <a href="api/ng/directive/ngRequired">ngRequired</a> will also add
  144 <code>aria-required</code>. This tells accessibility APIs when a custom control is required.</p>
  145 <h3 id="example">Example</h3>
  146 <pre><code class="lang-html">&lt;md-checkbox ng-required=&quot;val&quot;&gt;&lt;/md-checkbox&gt;
  147 </code></pre>
  148 <p>Becomes:</p>
  149 <pre><code class="lang-html">&lt;md-checkbox ng-required=&quot;val&quot; aria-required=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
  150 </code></pre>
  151 <h2 id="ngreadonly">ngReadonly</h2>
  152 
  153 <p>The boolean <code>readonly</code> attribute is only valid for native form controls such as <code>input</code> and
  154 <code>textarea</code>. To properly indicate custom element directives such as <code>&lt;md-checkbox&gt;</code> or <code>&lt;custom-input&gt;</code>
  155 as required, using ngAria with <a href="api/ng/directive/ngReadonly">ngReadonly</a> will also add
  156 <code>aria-readonly</code>. This tells accessibility APIs when a custom control is read-only.</p>
  157 <h3 id="example">Example</h3>
  158 <pre><code class="lang-html">&lt;md-checkbox ng-readonly=&quot;val&quot;&gt;&lt;/md-checkbox&gt;
  159 </code></pre>
  160 <p>Becomes:</p>
  161 <pre><code class="lang-html">&lt;md-checkbox ng-readonly=&quot;val&quot; aria-readonly=&quot;true&quot;&gt;&lt;/md-checkbox&gt;
  162 </code></pre>
  163 <h2 id="ngshow">ngShow</h2>
  164 
  165 <p>The <a href="api/ng/directive/ngShow">ngShow</a> directive shows or hides the
  166 given HTML element based on the expression provided to the <code>ngShow</code> attribute. The element is
  167 shown or hidden by removing or adding the <code>.ng-hide</code> CSS class onto the element.</p>
  168 <p>In its default setup, ngAria for <code>ngShow</code> is actually redundant. It toggles <code>aria-hidden</code> on the
  169 directive when it is hidden or shown. However, the default CSS of <code>display: none !important</code>,
  170 already hides child elements from a screen reader. It becomes more useful when the default
  171 CSS is overridden with properties that don’t affect assistive technologies, such as <code>opacity</code>
  172 or <code>transform</code>. By toggling <code>aria-hidden</code> dynamically with ngAria, we can ensure content visually
  173 hidden with this technique will not be read aloud in a screen reader.</p>
  174 <p>One caveat with this combination of CSS and <code>aria-hidden</code>: you must also remove links and other
  175 interactive child elements from the tab order using <code>tabIndex=“-1</code> on each control. This ensures
  176 screen reader users won&#39;t accidentally focus on &quot;mystery elements&quot;. Managing tab index on every
  177 child control can be complex and affect performance, so it’s best to just stick with the default
  178 <code>display: none</code> CSS. See the <a href="http://www.w3.org/TR/aria-in-html/#fourth-rule-of-aria-use">fourth rule of ARIA use</a>.</p>
  179 <h3 id="example">Example</h3>
  180 <pre><code class="lang-css">.ng-hide {
  181   display: block;
  182   opacity: 0;
  183 }
  184 </code></pre>
  185 <pre><code class="lang-html">&lt;div ng-show=&quot;false&quot; class=&quot;ng-hide&quot; aria-hidden=&quot;true&quot;&gt;&lt;/div&gt;
  186 </code></pre>
  187 <p>Becomes:</p>
  188 <pre><code class="lang-html">&lt;div ng-show=&quot;true&quot; aria-hidden=&quot;false&quot;&gt;&lt;/div&gt;
  189 </code></pre>
  190 <p><em>Note: Child links, buttons or other interactive controls must also be removed from the tab order.</em></p>
  191 <h2 id="nghide">ngHide</h2>
  192 
  193 <p>The <a href="api/ng/directive/ngHide">ngHide</a> directive shows or hides the
  194 given HTML element based on the expression provided to the <code>ngHide</code> attribute. The element is
  195 shown or hidden by removing or adding the <code>.ng-hide</code> CSS class onto the element.</p>
  196 <p>The default CSS for <code>ngHide</code>, the inverse method to <code>ngShow</code>, makes ngAria redundant. It toggles
  197 <code>aria-hidden</code> on the directive when it is hidden or shown, but the content is already hidden with
  198 <code>display: none</code>. See explanation for <a href="guide/accessibility#ngshow">ngShow</a> when overriding the default CSS.</p>
  199 <h2><span id="ngclick">ngClick</span> and <span id="ngdblclick">ngDblclick</span></h2>
  200 If <code>ng-click</code> or <code>ng-dblclick</code> is encountered, ngAria will add <code>tabindex=&quot;0&quot;</code> to any element not in
  201 the list of built in aria nodes:
  202 
  203  <em> Button
  204  </em> Anchor
  205  <em> Input
  206  </em> Textarea
  207  <em> Select
  208  </em> Details/Summary
  209 
  210 To fix widespread accessibility problems with <code>ng-click</code> on <code>div</code> elements, ngAria will
  211 dynamically bind a keypress event by default as long as the element isn&#39;t in a node from the list of
  212 built in aria nodes.
  213 You can turn this functionality on or off with the <code>bindKeypress</code> configuration option.
  214 
  215 ngAria will also add the <code>button</code> role to communicate to users of assistive technologies. This can
  216 be disabled with the <code>bindRoleForClick</code> configuration option.
  217 
  218 For <code>ng-dblclick</code>, you must still manually add <code>ng-keypress</code> and a role to non-interactive elements
  219 such as <code>div</code> or <code>taco-button</code> to enable keyboard access.
  220 
  221 <h3>Example</h3>
  222 <code>html
  223 &lt;div ng-click=&quot;toggleMenu()&quot;&gt;&lt;/div&gt;</code>
  224 
  225 Becomes:
  226 <code>html
  227 &lt;div ng-click=&quot;toggleMenu()&quot; tabindex=&quot;0&quot;&gt;&lt;/div&gt;</code>
  228 
  229 <h2 id="ngmessages">ngMessages</h2>
  230 
  231 <p>The ngMessages module makes it easy to display form validation or other messages with priority
  232 sequencing and animation. To expose these visual messages to screen readers,
  233 ngAria injects <code>aria-live=&quot;assertive&quot;</code>, causing them to be read aloud any time a message is shown,
  234 regardless of the user&#39;s focus location.</p>
  235 <h3 id="example">Example</h3>
  236 <pre><code class="lang-html">&lt;div ng-messages=&quot;myForm.myName.$error&quot;&gt;
  237   &lt;div ng-message=&quot;required&quot;&gt;You did not enter a field&lt;/div&gt;
  238   &lt;div ng-message=&quot;maxlength&quot;&gt;Your field is too long&lt;/div&gt;
  239 &lt;/div&gt;
  240 </code></pre>
  241 <p>Becomes:</p>
  242 <pre><code class="lang-html">&lt;div ng-messages=&quot;myForm.myName.$error&quot; aria-live=&quot;assertive&quot;&gt;
  243   &lt;div ng-message=&quot;required&quot;&gt;You did not enter a field&lt;/div&gt;
  244   &lt;div ng-message=&quot;maxlength&quot;&gt;Your field is too long&lt;/div&gt;
  245 &lt;/div&gt;
  246 </code></pre>
  247 <h2 id="disabling-attributes">Disabling attributes</h2>
  248 <p>The attribute magic of ngAria may not work for every scenario. To disable individual attributes,
  249 you can use the <a href="api/ngAria/provider/$ariaProvider#config">config</a> method. Just keep in mind this will
  250 tell ngAria to ignore the attribute globally.</p>
  251 <p>
  252 
  253 <div>
  254   <plnkr-opener example-path="examples/example-accessibility-ng-click"></plnkr-opener>
  255 
  256   <div class="runnable-example"
  257       path="examples/example-accessibility-ng-click"
  258       module="ngAria_ngClickExample"
  259       deps="angular-aria.js"
  260       name="accessibility-ng-click">
  261 
  262   
  263     <div class="runnable-example-file" 
  264       name="index.html"
  265       language="html"
  266       type="html">
  267       <pre><code> &lt;div ng-click=&quot;someFunction&quot; show-attrs&gt;&#10;   &amp;lt;div&amp;gt; with ng-click and bindRoleForClick, tabindex set to false&#10; &lt;/div&gt;&#10;&lt;script&gt;&#10; angular.module(&#39;ngAria_ngClickExample&#39;, [&#39;ngAria&#39;], function config($ariaProvider) {&#10;   $ariaProvider.config({&#10;     bindRoleForClick: false,&#10;     tabindex: false&#10;   });&#10; })&#10; .directive(&#39;showAttrs&#39;, function() {&#10;   return function(scope, el, attrs) {&#10;     var pre = document.createElement(&#39;pre&#39;);&#10;     el.after(pre);&#10;     scope.$watch(function() {&#10;       var attrs = {};&#10;       Array.prototype.slice.call(el[0].attributes, 0).forEach(function(item) {&#10;         if (item.name !== &#39;show-attrs&#39;) {&#10;           attrs[item.name] = item.value;&#10;         }&#10;       });&#10;       return attrs;&#10;     }, function(newAttrs, oldAttrs) {&#10;       pre.textContent = JSON.stringify(newAttrs, null, 2);&#10;     }, true);&#10;   }&#10; });&#10;&lt;/script&gt;</code></pre>
  268     </div>
  269   
  270 
  271     <iframe class="runnable-example-frame" src="examples/example-accessibility-ng-click/index.html" name="example-accessibility-ng-click"></iframe>
  272   </div>
  273 </div>
  274 
  275 
  276 </p>
  277 <h2 id="common-accessibility-patterns">Common Accessibility Patterns</h2>
  278 <p>Accessibility best practices that apply to web apps in general also apply to AngularJS.</p>
  279 <ul>
  280 <li><strong>Text alternatives</strong>: Add alternate text content to make visual information accessible using
  281 <a href="http://www.w3.org/TR/html-alt-techniques/">these W3C guidelines</a>. The appropriate technique
  282 depends on the specific markup but can be accomplished using offscreen spans, <code>aria-label</code> or
  283 label elements, image <code>alt</code> attributes, <code>figure</code>/<code>figcaption</code> elements and more.</li>
  284 <li><strong>HTML Semantics</strong>: If you&#39;re creating custom element directives, Web Components or HTML in
  285 general, use native elements wherever possible to utilize built-in events and properties.
  286 Alternatively, use ARIA to communicate semantic meaning. See <a href="http://www.w3.org/TR/aria-in-html/#notes-on-aria-use-in-html">notes on ARIA use</a>.</li>
  287 <li><strong>Focus management</strong>: Guide the user around the app as views are appended/removed.
  288 Focus should <em>never</em> be lost, as this causes unexpected behavior and much confusion (referred to
  289 as &quot;freak-out mode&quot;).</li>
  290 <li><strong>Announcing changes</strong>: When filtering or other UI messaging happens away from the user&#39;s focus,
  291 notify with <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">ARIA Live Regions</a>.</li>
  292 <li><strong>Color contrast and scale</strong>: Make sure content is legible and interactive controls are usable
  293 at all screen sizes. Consider configurable UI themes for people with color blindness, low vision
  294 or other visual impairments.</li>
  295 <li><strong>Progressive enhancement</strong>: Some users do not browse with JavaScript enabled or do not have
  296 the latest browser. An accessible message about site requirements can inform users and improve
  297 the experience.</li>
  298 </ul>
  299 <h2 id="additional-resources">Additional Resources</h2>
  300 <ul>
  301 <li><a href="http://www.w3.org/TR/aria-in-html/">Using ARIA in HTML</a></li>
  302 <li><a href="https://www.youtube.com/watch?v=dmYDggEgU-s&amp;list=UUEGUP3TJJfMsEM_1y8iviSQ">AngularJS Accessibility at ngEurope</a></li>
  303 <li><a href="http://webaim.org/articles/screenreader_testing/">Testing with Screen Readers</a></li>
  304 <li><a href="https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb?hl=en">Chrome Accessibility Developer Tools</a></li>
  305 <li><a href="http://www.w3.org/wiki/Accessibility_testing">W3C Accessibility Testing</a></li>
  306 <li><a href="http://webaim.org">WebAIM</a></li>
  307 <li><a href="http://a11yproject.com">A11y Project</a></li>
  308 </ul>
  309 
  310