ホームページ >ウェブフロントエンド >htmlチュートリアル >WAI-ARIA アクセス可能な Web 仕様_html/css_WEB-ITnose
アクセシブルなデザインとは、製品、機器、サービス、環境が障害のある人向けに設計されていることを意味します。アクセシブルなデザインの概念は、人の支援技術 (コンピューターのスクリーン リーダーなど) との互換性を意味し、直接アクセス (つまり独立) と「間接アクセス」を保証します。
アクセシブル デザインは「アクセシブル」として理解でき、身体障害のある人、特別なニーズを持つ人、または支援技術に依存している人が Web にアクセスできるようにすることに重点を置いているシステムまたはエンティティにとって有益です。そして、アクセシブルなデザインを研究開発することは、すべての人に利益をもたらします。
アクセシビリティのデザインをユーザビリティと混同しないでください。 ほとんどの場合、ユーザビリティとは、指定された目標を効果的に達成するために、特定の環境で特定のユーザーが使用できる製品 (デバイス、サービス、環境など) の能力を指します。
アクセシブルデザインとユニバーサルデザインは密接な関係があります。ユニバーサルデザインとは、さまざまな状況であらゆる能力や業務を行う人々が利用できる、可能な限り幅広い人々が利用できる製品を作成するプロセスを指します。つまり、(アクセスの障害の有無に関係なく)誰もがアクセスできる製品です。ウェブ)。
HTML、CSS、JavaScript を使用してリッチ インターネット アプリケーションを作成する場合、開発者は障害を持つ人々を置き去りにすることがよくあります。これらのアプリケーションは、支援技術が必要なセマンティック情報を理解できる機能を提供していないためです。 。残念ながら、これまでのところ大きな変化はありませんが、実際にこの状況を逆転させることはできます。 WAI-ARIA は、リッチ インターネット アプリケーションを理解できるようにするために十分なセマンティクスを提供でき、現在では比較的よくサポートされています。
ARIA は、「**Accessible Rich Internet Applications**」の略称です。これは、W3C の Web Accessibility Initiative (WAI) によって 2014 年 3 月 20 日にリリースされた、Accessible Rich Internet Application Implementation Guide (アクセシブル リッチ インターネット アプリケーション実装ガイド) です。
WAI-ARIA は、障害を持つ人々に動的でインタラクティブな Web コンテンツへのバリアフリー アクセスを提供する技術仕様です。 WAI-ARIA およびその他のサポート文書については、「WAI-ARIA の概要」で説明されています。
簡単な説明:
HTML に適用される ARIA には、**role** (役割) と 2 つの部分があります。 **aria-** で始まる属性。その役割は次のとおりです:
ARIAはHTML内で使用されます 独自の仕様があり、これは、HTML で ARIA を使用すると Web ページがアクセス可能になり、アクセシビリティが向上するという意味ではありません。つまり、ARIA をうまく使用しないと、別の落とし穴に陥り、ページがアクセスしにくくなるということです。
HTML での ARIA に関するドキュメントは、ここで読むことができます。
使用する要素 (HTML5) がセマンティックである場合、これらの要素を再定義せずに使用する必要があります。 ARIA のロール、状態、または属性を追加します。
それでは、ARIA がいつ利用可能になり、いつ利用できなくなるのでしょうか?
は、実際に使用する必要がない限り、セマンティクスを変更しません。たとえば、開発者はタイトルを作成したいと考えていますが、それはボタンです。
これは行わないでください:
<h1 role=button>标题按钮</h1>
これを行うことをお勧めします:
<h1><button>标题按钮</button></h1>
あるいは、正しい要素を使用していませんが、次のようにすることもできます。
<h1><span role=button>标题按钮</span></h1>
すべての ARIA コントロールにはキーボード イベントが必要です。
コンポーネント (ウィジェット) を作成すると、ユーザーはキーボードを使用して、作成したコンポーネントを見つけて、対応する操作を実行できます。
例如,如果使用 role=button 必须能够接收到焦点和用户能够使用键盘激活相应动作,比如Win操作系统上的 enter 和iOS系统上的 return 或者键盘的空格键( space )。
不建议在可获取焦点元素( focusable )使用ARIA的角色: role=presentation 或 aria-hidden="true" 。
可获取焦点元素上使用ARIA这两规则,会导致一些用户无法获取元素焦点。
不要这样做:
<button role=presentation>按下我,按下我</button>
也不要这样做:
<button aria-hidden="true">按下我,按下我</button>
如果说一个交互元素无法看到或者不能与之交互,那么可以尝试使用 aria-hidden ,例如:
button {visibility:hidden}<button aria-hidden="true">按下我,按下我</button>
所有交互元素都必须有一个 可访问的名称 。
当可交互元素的可访问性API的可访问名属性只有一个值时,那么可交互元素就只有一个可访问的名称。
比如下面的示例, input type="text" 有一个可见的 2e1cf0710519d5598b1f0f14c36ba674 标签,但它并没有可访问的名称:
user name <input type="text">
或者:
<label>user name</label><input type="text" />
此时MSAA( Microsoft Active Accessibility )控制器的 accName 属性是空的:
相比之下,下面示例中 input type="text" 有一个可见的 2e1cf0710519d5598b1f0f14c36ba674 标签并且包含一个可访问性名称:
或者:
<label for="uname">user name</label> <input type="text" id="uname">
此时MSAA( Microsoft Active Accessibility )控制器的 accName 属性值是 user name :
另外 label 标签元素是不能被用来给自定义控件提供一个访问性名称,除非 label 引用了HTML的 labelable 元素 。
<!-- HTML input element with combox role --> <label> user name <input type="text" role="combobox" > </label>
MSAA( Microsoft Active Accessibility )控制器的 accName 属性值是 user name :
除此之外,使用非HTML labelable 元素来模拟控件,不管给其分配什么角色( role )都不会是HTML的 labelable 元素,比如下面的 div 元素:
<!-- HTML div element with combox role --> <label> user name <div role="combobox"></div> </label>
MSAA( Microsoft Active Accessibility )控制器的 accName 属性值是空的:
下面的表格详细的示意了HTML中元素如何使用ARIA的角色 role ,以及对应的含意:
role 属性值 | 含义 | HTML示意 | 说明 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
alert | 表示警告 | 956b8be0af4e1df0225d30cdac97363d...16b28748ea4df4d9c2150843fecfba68 | ajax操作返回错误信息的 div 标签 如Bootstrap中的 Alert组件 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dialog | 表示Modal弹出窗 | cf1f44773360d4dd283cbec282a13baa...16b28748ea4df4d9c2150843fecfba68 | 自定义的弹出框,如Bootstrap中的 Modal组件 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
presentation | 表示描述 | 06f4eaf10152472974b293f44ebf84a7text473f0a7621bec819994bb5020d29372a | 删除HTML元素的语义化角色。加上后, 可访问树 就变成: 【注释一】 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
application | 表示应用 | 1f9bbc63d4f37e733da743f423e32f55...16b28748ea4df4d9c2150843fecfba68 | 例如自定义的时间选择器 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
button | 表示按钮 | a94df0d86bf32804df923886e2df70ef54bdf357c58b8a65c66d7c19c8e4d114 | 使用 span 元素模拟按钮控件 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checkbox | 表示复选框 | 5fd0c0c55b6cabf75deb7f9159950cbb16b28748ea4df4d9c2150843fecfba68 | 使用 div 模拟复选框 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
radio | 表示单选按钮 | 12b274308dfe8663f5755110304866ea16b28748ea4df4d9c2150843fecfba68 | div 要素を使用してラジオ ボタンをシミュレートします | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
コンボボックス | はフォーム コントロールを表します | d34a41a46178b782388725e872042aed | 入力要素、その type 属性値はテキスト、検索、電話、URL、または電子メールです。そして、aria-owns 属性値は list 属性と同じ値に設定されます。さらに、select 要素に multiple 属性がないか、size 属性の値が 1 より大きいです。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
グリッド | はグリッド | 7b7fae51df3226f3a8a3a3ebd3b68466945beea452e97a9c4c21958a6cf4a858f16b1740fad44fb09bfe928bcc527e0816b28748ea4df4d9c2150843fecfba68 | グリッドを表します | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
グリッドセル | グリッド セル | 8c8db3ce840dcc553a2470225e1dbb7520d73c495a3a1d9f7d535dda82656888Fidob90dd5946f0946207856a8a37f441edffd273fcf5bcad3dfdad3c41bd81ad3e5 | td の祖先要素 (または table 要素) は role="grid" を定義します (列ヘッダーまたは行ヘッダー、およびその祖先要素または table 要素は role="grid" を定義します) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
グループ | はグループの合併を意味します | 726f83a703a577338399237a7d52531e...< ; /div> | たとえば、Bootstrap のボタンの組み合わせ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
はタイトル | を表します。26dcf2fd109e9cd337e365ff3dd9a4e716b28748ea4df4d9c2150843fecfba68 | div を使用して h1 をシミュレートします | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
はリストボックス | 03177812657af983cb5f8daa1fb3806a | を表します。複数の属性とサイズ値を使用してシミュレートします。1 より大きい select 要素、または aria-multiselectable 属性値が false に設定されたデータリストです。たとえば、ドロップダウン選択ボックスのリスト項目をシミュレートするには、ul を使用します。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
はメニュー | 09061e7dd94e918293df406be33e7ff1929d1f5ca49e04fdcb27f9465b944689 🎜> | メニューバー | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ca4270b077b71bc70a2e4200429ac82656e94d4ba92f2baf1774087ad456d23d09061e7dd94e918293df406be33e7ff1929d1f5ca49e04fdcb27f9465b944689bed06894275b65c1ab86501b08a632eb929d1f5ca49e04fdcb27f9465b944689 | menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
を表します ca4270b077b71bc70a2e4200429ac82659fae43104701bc9d521b4efcf62746671f222dda32f633bac8ada2e55f1eaab929d1f5ca49e04fdcb27f9465b944689bed06894275b65c1ab86501b08a632eb929d1f5ca49e04fdcb27f9465b944689 | menuitemcheckbox | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
09061e7dd94e918293df406be33e7ff1c0b4755691fa52dd39d0b5782ebd93bbbed06894275b65c1ab86501b08a632eb929d1f5ca49e04fdcb27f9465b944689 | menuitemradio | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6eb6b12b185abf0b5c8812a1e395ff7cbed06894275b65c1ab86501b08a632eb929d1f5ca49e04fdcb27f9465b944689 | オプション | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
03177812657af983cb5f8daa1fb3806a5b142be18c1738834e706572a52bd388bed06894275b65c1ab86501b08a632eb929d1f5ca49e04fdcb27f9465b944689 |
HTML元素 | ARIA ( role = ) | 备注 |
---|---|---|
a | link | 不带 href 属性的 a 元素不具有 role="link" |
a | menuitem | 父元素是一个菜单 |
article | article | |
aside | complementary | |
body | document | |
button | button | |
dd | definition | |
dialog | dialog | |
footer | contentinfo | |
form | form | |
h1~h6 | heading | 使用 aria-level 属性来设置标题的级别,对应的是 1~6 |
header | banner | |
hr | separator | |
img | img | |
input | button | input 的 type 属性为 button (或 image 、 reset 、 submit ) |
input | button | input 的 type 属性为 button (或 image ),并且其父元素是一个菜单 menu |
input | checkbox | input 的 type 属性设置为 checkbox ,并且 aria-checked 默认值为 mixed |
input | menuitemcheckbox | input 的 type 为 checkbox ,并且其父元素是一个菜单 |
input | textbox | input 的 type 为 text (或 password 、 search 、 telephone 、 email 、 url ) |
input | spinbutton | input 的 type 为 number |
input | slider | input 的 type 为 rang |
input | combobox | input 的 type 为 text 、 search 、 telephone 、 url 、 email ,并且 aria-owns 属性的值和 list 属性值一样 |
li | listitem | 父元素是 ol 或 ul 或 menu |
main | main | |
nav | navigation | |
ol 或 ul | list | |
optgroup | group | |
option | option | aria-selected 的默认值为 true |
progress | progressbar | aria-valuemax 设置最大值, aria-valumin 设置最小值, aria-valuenow 设置当前值 |
section | region | |
table | table | |
tbody | rowgroup | thead 对应的 role 值和 tbody 一样 |
td | cell | 祖先元素具有 table 的作用,如果祖先元素是一个 grid ,那么其 role 为 gridcell |
th | columnheader | 表格的列标题,表格的横标题对应的 role 为 rowheader |
tr | row |
通过一个示例来看看 role="presentation" 运用前后对HTML元素可访问树对比。
<table> <tr> <td> <table> <tr> <td> <abbr>API</abbr> </td> </tr> </table> </td> </tr></table>
在上面的代码上添加 role="presentation" :
<table role="presentation"> <tr> <td> <table> <tr> <td> <abbr>API</abbr> </td> </tr> </table> </td> </tr></table>
table 元素可访问树前后对比示意图如下:
前面也说到过,并不是在HTML中添加ARIA角色对屏幕阅读器就是好的,特别是对于一些默认带有交互功能的元素中,添加ARIA就是浪费时间,比如:
<button role="button">按我</button><h1 role="heading" aria-level="1">标题一</h1>
当然在HTML5的一些特定元素上,ARIA的 role 和自带的语义化元素是可以重叠的,如下表所示:
HTML5元素 | ARIA Role |
---|---|
1aa9e5d373740b65a0cc8f0a02150c53 | role="banner" |
c787b9a589a3ece771e842a6176cf8e9 | role="navigation" |
61b85035edf2b42260fdb5632dc5728a | role="main" |
c37f8231a37e88427e62669260f0074d | role="contentinfo" |
15221ee8cba27fc1d7a26c47a001eb9b | role="complementary" |
2f8332c8dcfd5c7dec030a070bf652c3 | role="region" |
23c3de37f2f9ebcb477c4a90aac6fffd | role="article" |
ff9c23ada1bcecdd1a0fb5d5a0f18437 | role="form" |
搜索表单 | role="search" |
假设有一个简单的HTML5页49f9febfc8d73a09c4f57cc69347ef3a8ab8216694297e4c0df980396ea2c26e16b28748ea4df4d9c2150843fecfba68
次の表は、ARIA 関連のステータスの使用方法を示しています。
属性状态 | 属性值 | HTML示意 | 说明 |
---|---|---|---|
aria-checked | 字符串。表示检查的状态。 true 表示元素被选择; false 表示元素未被选择; mixed 表示元素同时有选择和为选择状态。 | 9dd914035e65022da95b83d73a510dd6bed06894275b65c1ab86501b08a632eb | 该属性用来表明用户是否选择了某些项,类似于 input type="checkbox" 中的 checked |
aria-disabled | 字符串。表禁用状态, true 表示当前是非激活状态; false 表示清除非激活状态。 | 67f764bf205317ae34a5a8038e23636e16b28748ea4df4d9c2150843fecfba68 | 对应单复选框等控件的 disabled 属性,一般用在自定义模拟控件中 |
aria-expanded | 字符串。表示展开状态。默认为 undefined , 表示当前展开状态未知。其它可选值: true 表示元素是展开的; false 表示元素不是展开的。 | ||
aria-hidden | 字符串。可选值为 true 和 false , true 表示元素隐藏(不可见), false 表示元素可见。 | 53ca730cb8a1ef154f15971e987d07ef16b28748ea4df4d9c2150843fecfba68 | 该属性使用非常普遍。几乎所有涉及到显示与隐藏这类交互或没有交互的地方都可以应用该属性。左边的示例HTML代码来自进度条进度值显示的 div , 当前 aria-hidden 为 false , 表示该进度值是可见的。 |
aria-invalid | 字符串。表示元素值是否错误的。默认为 false , 表示是OK的,如果为 true , 则表示值验证不通过。 | 431ad8dbd9590c59b203264bc71cf390 | |
aria-pressed | 字符串。表示按下的状态,可选值有: true , false , mixed , undfined 。默认为 undfined , 表示按下状态未知; true 表示元素往下(按钮按下); false 表示元素抬起; mixed 表示元素同时有按下和没有按下的状态。 | 67f764bf205317ae34a5a8038e23636e16b28748ea4df4d9c2150843fecfba68 | 左边HTML表示按钮已经按下,同时处于禁用状态。 |
aria-selected | 字符串。表示选择状态。可选值有: true , false , undefined 。 默认为 undefined ,表示元素选择状态未知。 true 表示元素已选择; false 表示未被选中。 |
Roles | States | Properties |
---|---|---|
alert | aria-busy | aria-activedescendant |
alertdialog | aria-expanded | aria-atomic |
gridcell | aria-grabbed | aria-controls |
log | aria-hidden | aria-describedby |
marquee | aria-pressed | aria-dropeffect |
menuitemcheckbox | aria-flowto | |
menuitemradio | aria-haspopup | |
scrollbar | aria-label | |
status | aria-labelledby | |
tab | aria-level | |
tabpanel | aria-live | |
timer | aria-orientation | |
tooltip | aria-owns | |
treeitem | aria-posinset | |
grid | aria-relevant | |
menu | aria-setsize | |
menubar | aria-sort | |
tablist | ||
toolbar | ||
tree | ||
treegrid | ||
directory | ||
document | ||
group | ||
note | ||
presentation | ||
region | ||
application | ||
search |
开发一个可访问的 Web 应用不仅需要工具的支持,浏览器的支持,还需要开发人员遵循一定的规范提供对应的元素信息,才能达到最终的目的。下面着重介绍一些开发中的最佳实践。
图片或者动画均需提供 alt 信息,使得读屏软件可以将图片动画的内容清楚的读出来。如图所示:
对应的 HTML 如下:
<img src="cat.gif" alt="Image about cat" />
对于某些用于装饰性的图片,则需设置 alt 为空,使得读屏软件可以忽略此元素。如图用于装饰页头的图片,实际并没有传递有价值的信息。
对应的 HTML 如下:
<img src="ring.gif" alt="" />
必须设置一个空 alt 属性的目的是为了能通过 Webking 的检查,并且使得读屏软件能够忽略此元素。
对于图表文件, alt 属性的设置则需要简明扼要的表达出图表的信息,并不用把里面的细节都详细得描述出来。例如下面的图 alt 信息设置为销售额从 1996 年到 2004 年间持续稳定增长,从 400 万增长到了 1600 万。并不需要把每一年的增长额都详细得描述出来。
对于放在链接里面的图片,如果已经有文字的说明, alt 也设置为空,这样避免读屏软件重复同样的内容。如下面的 HTML:
<a href=”http://apple.com/iphone/”> <img src=”iphone.jpg” alt=””>Apple iPhone </a>
a 的内容已经指明了这是个苹果手机, img 的 alt 属性就没必要再设置一次了。否则读屏软件会连续读两次重复的内容,引起混乱。
CSS 将样式跟结构分离,使得 HTML 代码结构清晰。很多装饰性的图片也都放在 CSS 里面来加载,带来的一个问题就是在 CSS 里面的图片在高对比度模式下都无法显示。如果这个图片并不仅仅是装饰性的,还可以触发功能,那就需要从 CSS 里面拿出来,当成一个独立的 img 或者 input 元素。例如下面的一个提示保存的图片
写在 CSS 里面的做法是:
<div class=” save_button” ></div> .save_button{ background: url("images/save_button.png"); width: 33px; height: 33px; vertical-align:middle; }
这样当用户切换到高对比度模式,这个图片就是一片空白,用户无法再去点击保存。修改如下:
<img src=“images/save_button.png” alt=“save”/> <input type=“image” src=“images/save_button.png” alt=“save”/>
在一个图片列表里面选中某个图片,区别选中去否我们通常的做法是用边框的颜色来标识。如下图,选中的图片边框为蓝色
.selectedIcon{ border:5px solid #ACC6F3; } .unSelectedIcon{ border:5px solid #C0D4F7; }
但这样的一个实现实际上违反了可访问检查列表中的一项:不能仅仅通过颜色来区分不同的元素,因为在高对比度下只有黑色或白色,这样的区分在高对比度下是没有任何作用的。我们很容易想到的一种办法就是只有选中的时候才加边框,未选中时则没有边框,这样就可以区分出来了。修改如下:
.selectedIcon{ border:5px solid #ACC6F3; } .unSelectedIcon{ border:0 none; }
这样引起的问题是,图片的布局在选中的时候会浮动,增加了 5px 的边框,看起来效果就很差。那么怎么保证布局又满足可访问性的要求呢? 可以在上面 CSS 的基础上通过 padding 属性使得布局正确:
.selectedIcon { border:1px solid #ACC6F3; padding:4px;} .unSelectedIcon { border:0 none; padding:5px;}
这样保证整体的边界都是 5px ,在高对比度下的效果如图所示:
Table 分为两类:一类是做布局的 table ,一类是数据 table 。对于布局用的 table ,读屏软件没必要知道这是一个表,可以通过设置 role=presentation 使 JAWS 忽略这个表,只关注里面的内容。对于数据表格,则需要设置 caption 属性,说明整个表是用来做什么的,使得 JAWS 可以告诉用户这个表的作用。对于每一个单元内的数据,还应该通过 th 属性使得 JAWS 能识别这个数据的表头是什么。对于复杂表,可以通过 id 和 header 属性来标识。如图所示 :
以第一行的数字 5 为例,正常人可以很容易得看出 5 指的是一年级 Mr.Henry 老师这个班的男生有 5 个,但当 JAWS 面对这个数字 5 的时候,怎么能识别出来呢?通过 header 来标识表头, header 的值就指向对应表头的 id 。对应的 HTML 如下:
<tr> <th id="class"> Class </th> <th id="teacher"> Teacher </th> <th id="boys"> #of Boys </th> <th id="girls"> #of Girls </th> </tr> <tr> <th id="1stgrade" rowspan="2"> 1st Grade </th> <th id="MrHenry" headers="1stgrade teacher"> Mr . Henry </th> <td headers="1stgrade MrHenry boys"> 5 </td> <td headers="1stgrade MrHenry girls"> 4 </td> </tr> <tr> <th id="MrsSmith" headers="1stgrade teacher"> Mrs . Smith </th> <td headers="1stgrade MrsSmith boys"> 7 </td> <td headers="1stgrade MrsSmith girls"> 9 </td> </tr> <tr> <th id="2ndgrade" rowspan="3"> 2nd Grade </th> <th id="MrJones" headers="2ndgrade teacher"> Mr . Jones </th> <td headers="2ndgrade MrJones boys"> 3 </td> <td headers="2ndgrade MrJones girls"> 9 </td> </tr> <tr> <th id="MrsSmith" headers="2ndgrade teacher"> Mrs . Smith </th> <td headers="2ndgrade MrsSmith boys"> 4 </td> <td headers="2ndgrade MrsSmith girls"> 3 </td> </tr> <tr> <th id="MrsKelly" headers="2ndgrade teacher"> Mrs . Kelly </th> <td headers="2ndgrade MrsKelly boys"> 6 </td> <td headers="2ndgrade MrsKelly girls"> 9 </td> </tr>
form 元素需要关联一个 label 元素,所有的 button 都已经有了一个隐含的 label ,所以不再需要显示关联。对于 input , select , checkbox , radio , button 则都需要显示一个 label 元素。这样 JAWS 在面对这个表单元素的时候才能告诉用户这个表单的作用。例如下面的 input , JAWS 会告诉用户这个是需要输入名字的一个输入框。当 label 属性不方便使用的时候,还可以通过 title 属性达到相同的效果,也可以满足 Webking 检查的需要。下面的两种写法都可以。但前提是 name 不需要被显示出来。当 title 和 label 都设置的时候 title 会被 JAWS 忽略。
<label for="name1">Name:</label> <input name="name" id="name1" size="30" /> 或 <input name=”name” id=”name1” size=”30” title=”name”>
当一个表单元素如果前后都需要描述的时候, label 就显得力不从心了。ARIA 规范的出现解决了这一问题。 aria-labelledby 属性可以设置多个值,说明这个表单元素是被那些值所描述的, aria-describedby 属性则更详细的扩展了这个描述。如下图所示:
当 JAWS 把焦点放在 10 上的时候,会告诉用户 10 表示的是 10 分钟刷新一次。对应的 HTML 代码如下所示。 aria-required 的属性标识这个元素是必须的,JAWS 识别此元素并告知用户必须输入此元素。我们可以看到中间的 input 元素被多个元素来描述( aria-labelledby 中的几个 id 值),这样 JAWS 就能够识别这个标签,并且按照这个标签的顺序读出前后的 label , 并且提示用户如果还有更详细的描述以及如何获取这个更详细的描述。当用户需要时, aria-describedby 所对应的元素信息就会被读出来。增强了视力有障碍人士与普通人了解内容的一致性。
<div> <span id="labelRefresh"> <label for=“refreshTime">Refresh after</label> </span> <input id=“refreshTime" type="text" aria-describedby=“refreshDescriptor" aria-labelledby=" labelRefresh refreshTime refreshUnit" value="10"/> <span id=“refreshUnit"> minutes</span> </div> <div id=“refreshDescriptor">Allows you to specify the number of minutes of refresh time.</div>
Tabindex 属性的使用可以使得原本无法取得焦点的元素获取焦点。目的是为了使用户可以用键盘访问任何可以用鼠标访问的元素。我们知道,使用 Tab 键可以按文档顺序 tab 到所有可以获取焦点的元素。 tabindex 可以设置为 -1 , 0 或者是任何自然数。
当用户使用 Tab 键浏览页面时,元素获取焦点的顺序是按照 HTML 代码里面元素出现的顺序排列的,有时跟实际看到的页面顺序并不一致。例如图 所示的页面:
按照页面顺序,tab 的顺序为自左向右,可实际上操作的时候却发现“search all”出现在了“go to edit”的前面。对应的 HTML 代码如下所示:
<!-- 页面获取 focus 的顺序 --><div> <span style=”float:left;”>welcome page</span> <span style=”float:right;margin-left:6em;”>search all</span> <span style=”float:right;”>go to edit</span></div>
原来是通过 float:right 达到了布局上的效果,实际文档顺序确实是 search all 在前面的。所以为了不引起混淆,最后能保持代码的顺序与实际呈现出来的页面上的顺序一致。可以修改上面的代码为,如下所示:
<!-- 页面获取 focus 的顺序 调整后 --><div> <span style=”float:left;”>welcome page</span> <span style=”float:right;width:15em;”> <span style=”float:left;”>go to edit</span> <span style=”float:right;”>search all</span> </span></div>
隐藏的内容分为两种,一种是为了布局的需要,在条件满足的情况下才会显示出来;另一种是只给读屏软件读的内容:有时候我们为了使读屏软件更准确的读取信息,会提供一些额外的描述来达到此效果,但为了不给正常用户带来困扰,这些内容对正常用户来说是隐藏起来的。隐藏内容我们通常用 display:none 或者 visibility:hidden 来表示,但读屏软件同样也会忽略这类内容。那如何隐藏内容又能使读屏软件读出来呢?另外一种隐藏内容的方式是使用绝对定位使得内容不出现在当前屏幕上,如: {position:absolute;top:-30000px;} 所以在选择使用哪种方式隐藏内容时就需要慎重考虑, display:none visibility:hidden 对任何人都是隐藏的,如果想只给读屏软件读到就需要使用上面的绝对定位方式。例如在下图所示的菜单的选中项上加上如下的 css:
<!-- 只给读屏软件读的内容 --><span class="access"> is selected</span> .access{ position:absolute; top:-30000px;}
这样当用户使用 JAWS 浏览每一个菜单项时,在选中项上就能听到哪一项是当前的所选中。
系统切换到高对比度模式,只有黑白两色,很多在正常模式下依靠颜色来区分的(如界面边界)都无法辨识了,写在 CSS 里面的很多图片也都无法显示出来。此时就需要在高对比度下增加边界或者另外 DOM 节点来显示同样的内容。Dojo 的 WAIState Api 提供了一种方式来判断系统是否处于高对比模式,如果是则在 body 上增加 dijit_a11y 的一个 CSS。这样可以在正常模式下显示一个 DOM 节点在高对比度下显示另外一个 DOM 节点,从而方便的区分。如下图所展示的正常模式与高对比模式下的对比:
正常模式下如左图所示,子菜单通过一个图片标识,但这个图片是在 CSS 里面设置的,切换到高对比度模式即无法显示出来。此时,我们增加一个在高对比度模式下才显示出来的节点,达到如图右所示的效果,在高对比度下显示一个 + 号。代码如下所示,在高对比模式下, dijit_a11y 加在 body 上,dijitMenuExpandA11y 所对应的 DOM 即应用右面的 CSS 得以显示出来。
<!-- 正常模式与高对比模式显示不同的 Dom 节点 --><td class="dijitReset dijitMenuArrowCell" waiRole="presentation"> <div dojoAttachPoint="arrowWrapper" style="visibility: hidden"> <img src="${_blankGif}" alt="" class="dijitMenuExpand"> <span class="dijitMenuExpandA11y">+</span> </div></td>tundra .dijitMenuExpand { width: 7px; height: 7px; background-image: url('images/spriteArrows.png'); background-position: -14px 0px;}.dijitMenuExpandA11y { display: none;}.dijit_a11y .dijitMenuExpandA11y { display: inline;}
ARIA前
<h2 class="offscreen">System Folders</h2><ul role="listbox"> <li role="option">Inbox</li> <li role="option">Drafts</li></ul><h2>Personal Folders</h2><ul role="listbox"> <li role="option">Folder 1</li> <li role="option">Folder 2</li></ul>
ARIA后
<ul role="listbox" aria-label="System Folders"> <li role="option">Inbox</li> <li role="option">Drafts</li></ul><h2 id="folders">Personal Folders</h2><ul role="listbox" aria-labelledby="folders"> <li role="option">Folder 1</li> <li role="option">Folder 2</li></ul>
<div role="alertdialog" aria-labelledby="hd" aria-describedby="msg"> <div id="hd">Confirm Close</div> <p id="msg">Your message has not been sent. Do you want tosave it in your Drafts folder?</p> <div> <button>Save to Drafts</button> <button>Don't Save</button> <button>Keep Writing</button> </div></div>
<p class="heading1" role="heading" aria-level="1" >Heading 1</p><p class="heading2" role="heading" aria-level="2" >Heading 2</p><p class="heading3" role="heading" aria-level="3" >Heading 3</p>
<div role="list"> <div role="listitem">...</div> <div role="listitem">...</div> <div role="listitem">...</div></div>
<span tabindex="0" role="button" class="...">Button?</span>
<span tabindex="0" role="button" aria-pressed="false" class="...">Option</span><span tabindex="0" role="button" aria-pressed="true" class="... pressed">Option</span>
<span tabindex="0" role="checkbox" aria-checked="false" class="...">Option</span><span tabindex="0" class="... checked" role="checkbox" aria-checked="true">Option</span>
<span tabindex="-1" role="radio" aria-checked="false" class="...">Yes</span><span tabindex="0" role="radio" aria-checked="true" class="... selected">No</span><span tabindex="-1" role="radio" aria-checked="false" class="...">Maybe</span>
<span tabindex="0" role="link" onclick="document.location(...)">link</span>
<span tabindex="0" onmouseover="..." onfocus="..." aria-describedby="tooltip" >...</span>...<span role="tooltip" id="tooltip"> this is the tooltip text</span>
<span role="status" >some form of status bar message...</span>
<span role="alert" >an alert message (no user interaction)</span>
<div tabindex="0" aria-valuemin="0" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-label="..." aria-valuenow="40" aria-valuetext="40% complete"> <span style="width:40%"></span></div>
<div role="menu"> <div role="menuitem"></div> <div role="menuitem"></div> <div role="menuitem"></div></div>
<div role="menubar"> <div role="menuitem"> <div role="menu"> <div role="menuitem"></div> <div role="menuitem"></div> <div role="menuitem"></div> </div> </div></div>
<div role="listbox" aria-activedescendant="opt2" tabindex="0"> <div role="option" id="opt1">Option 1</div> <div role="option" id="opt2" class="active">Option 2</div> <div role="option" id="opt3">Option 3</div></div>
<!-- similar to <select> --><input type="text" role="combobox" aira-expanded="true" aira-autocomplete="list" aria-owns="optlist" aira-activedescendant="opt2" /><div role="listbox" id="optlist"> <div role="option" id="opt1">Option 1</div> <div role="option" id="opt2" class="active">Option 2</div> <div role="option" id="opt3">Option 3</div></div>
<!-- list with selectable items, expand/collapse, nesting --><div role="tree"> <div role="treeitem">...</div> <div role="treeitem">...</div> <div role="treeitem">... <div role="group"> <div role="treeitem">...</div> <div role="treeitem">...</div> </div> </div></div>
<!-- interactive table/spreadsheet --><div role="grid"> <div role="row"> <div role="columnheader">...</div> <div role="columnheader">...</div> </div> <div role="row"> <div role="gridcell">...</div> <div role="gridcell">...</div> </div></div>
<button type="button" class="btn btn-default" aria-label="Left Align"> <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span></button>
<div class="dropdown"> <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> Dropdown <span class="caret"></span> </button> <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul></div>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuDivider"> ... <li role="separator" class="divider"></li> ...</ul>
<div class="btn-group" role="group" aria-label="First group"> <button type="button" class="btn btn-default">1</button> <button type="button" class="btn btn-default">2</button> <button type="button" class="btn btn-default">3</button> <button type="button" class="btn btn-default">4</button> </div>
<!-- Single button --><div class="btn-group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Action <span class="caret"></span> </button> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul></div>
<div class="input-group"> <span class="input-group-addon" id="basic-addon1">@</span> <input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1"></div><div class="input-group"> <input type="text" class="form-control" placeholder="Recipient's username" aria-describedby="basic-addon2"> <span class="input-group-addon" id="basic-addon2">@example.com</span></div>
<nav> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul></nav>
<div class="alert alert-warning alert-dismissible" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <strong>Warning!</strong> Better check yourself, you're not looking too good.</div>
<div class="progress"> <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"> 60% </div></div>