例如使用了 a 標簽制作了按鈕,如果不進行額外的優化,讀屏軟件在朗讀時會讀作"文字內容 鏈接",但實際上該 a 標簽是用作按鈕使用,因此可以在標簽上添加 role="button" 屬性。此時,讀屏軟件會讀作"文字內容 按鈕"。
可以看到,讀屏軟件在朗讀時會在結尾朗讀出元素的屬性,這也是無障礙優化中重要的一環。無障礙優化就是要解決如何使得元素的屬性被正確識別,如何使得元素的內容被清晰准確地朗讀,如何排除干擾元素等問題。在了解 WeRead
H5 的無障礙優化處理之前,首先需要了解 Web 無障礙開發的基礎知識,及讀屏軟件的工作方式(以 Apple VoiceOver 為例),可以參考以下資料:
-
頁面無障礙基礎知識:Accessible Rich Internet Applications (WAI-ARIA) 1.1
-
無障礙教程:可訪問性 - 學習 Web 開發 | MDN
-
讀屏軟件的使用:VoiceOver - iPhone 使用手冊
Android和iOS表現
安卓和ios的讀法可能會有不同,屬性在不同的瀏覽器上支持不同
DOM 的順序很重要
讀屏軟件在讀屏時默認按照 DOM 的順序朗讀,因此如果 DOM 的順序與內容的語義順序不一致,例如使用了 flex-direction: row-reverse; 使得內容的順序倒序顯示,會使得內容難以理解。因此盡量避免使用會影響到 DOM 視
覺順序的樣式,如果無法避免,需要手動設置 tabIndex 屬性,告知讀屏軟件正確的內容順序。
為非文本元素提供文本說明
關於Image
圖片或者動畫均需提供 alt 信息,對於某些用於裝飾性的圖片,則需設置 alt 為空,使得讀屏軟件可以忽略此元素。如圖用於裝飾頁頭的圖片,實際並沒有傳遞有價值的信息。
對於圖表文件,alt 屬性的設置則需要簡明扼要的表達出圖表的信息,並不用把里面的細節都詳細得描述出來。例如下面的圖alt 信息設置為銷售額從 1996 年到 2004 年間持續穩定增長,從 400 萬增長到了 1600 萬。並不需要把每一年的
增長額都詳細得描述出來。

<img> 標簽需要加上 alt 屬性,讀屏軟件會自動讀出 alt 的內容,例如 alt 內容為"一只目光洶洶凝視遠方的貓",那么會被讀作"一只目光洶洶凝視遠方的貓 圖像"。如果沒有添加 alt 屬性,那么僅會讀作"圖像",視障用戶會完全無法
理解其實際含義。但是,當 <img> 標簽出現在 <a> 標簽內部,作為一個圖像鏈接時,對於放在鏈接里面的圖片,如果已經有文字的說明,alt 也設置為空,這樣避免讀屏軟件重復同樣的內容。如下面的 HTML:
| <a href=”http://apple.com/iphone/”> <img src=”iphone.jpg” alt=””>Apple iPhone </a> |
a的內容已經指明了這是個蘋果手機,img 的 alt屬性就沒必要再設置一次了。否則讀屏軟件會連續讀兩次重復的內容,引起混亂。
視頻使用 title 屬性
與上面的 <img> 標簽相似,<video> 標簽需要加上 title 屬性,例如 title 內容為"一只正在奔跑的貓",那么會被讀作一只正在奔跑的貓 視頻"。
使用語義化的元素
盡量使用語義化標簽
語義化的 HTML 標簽,例如 <header> <footer> <nav> <section> <main> <aside> <button>,使用語義化的標簽,主要影響兩個方面:
-
選中元素時是否會整塊選中
-
朗讀時結尾會加上怎樣的修飾詞
其中默認設置下,目前僅 <button> 標簽可以使得選中元素時會整塊選中,而不單獨選中子元素。至於修飾詞這里列舉具體的情況:
-
<header>讀作"xxx 橫幅 標志性內容"。 -
<footer>讀作"xxx 頁腳 標志性內容"。 -
<nav>讀作"xxx 導航 標志性內容"。 -
<section>僅讀作"xxx",沒有結尾修飾詞。 -
<main>讀作"xxx 主要 標志性內容"。 -
<aside>讀作"xxx 補充 標志性內容"。 -
<button>讀作"xxx 按鈕"。 -
<a>讀作"xxx 鏈接"。
實際上,在瀏覽器內部,使用語義化標簽會隱式加上特定的 role 屬性,最后朗讀時的結尾修飾詞也正是這些 role 屬性的值以及分類,其他 role 的值朗讀時也可以以此類推,而以上標簽與 role 屬性具體對應的關系如下:

以上 role 屬性值的分類大多數都屬於標志性內容。
role 屬性
如果出於其他考慮,使用了非對應語義的標簽,例如開頭提到的使用 a 標簽實現按鈕,就需要添加 role="button" 屬性來聲明這是一個按鈕。同理,其他類似情況也可以這樣處理,主要的就是影響朗讀時的修飾詞。
禁用狀態使用 disabled 屬性
使用特定的 class 來增加禁用態樣式是常見的手法,但由於 class 語義並不能被讀屏軟件識別,因此讀屏時無法知道當前處於禁用態。可以改為使用 disabled 屬性實現禁用態,例如:
|
會讀作 搜索用戶 請輸入用戶名 變暗 搜索欄,讀屏軟件會用"變暗"這個詞表示搜索欄處於不可用的狀態。而對於沒有 disabled 屬性的標簽,例如 a 標簽,可以使用 aria-disabled 屬性達到同樣的效果。
可使用 aria 標簽向不存在原生語義的元素添加語義
-
aria-label="screen reader only label",用於添加朗讀時的描述,讀屏時會讀出其中的內容,而忽略標簽的原有的文字,例如為 a 標簽同時添加role="button"和aria-label="額外的按鈕描述",最終會朗讀
成"額外的按鈕描述 按鈕"。
-
aria-controls="main",用於給操作按鈕關聯控制區域,VoiceOver 上這個屬性沒有任何作用,但 PC 讀屏軟件中,添加了該屬性后,可以把焦點從按鈕快速移動到被控制區域。 -
aria-live="true",添加了該屬性的元素,在其內容發生變化時,讀屏軟件會自動讀出變化后的新內容。可以用於會動態刷新的元素,例如發現卡片上的“XXX人參與活動”,書城的換一批功能,用於監聽實時變化的數據。實際
效果可以參考這個 demo。
-
更多屬性詳見:https://www.w3.org/TR/wai-aria/。
動畫
可在 iOS 下通過 CSS 選擇器 @media(prefers-reduced-motion) 來針對開啟了“避免動畫”的用戶取消動畫。
隱藏屏幕外的元素
確保屏幕外的內容已通過 display: none 或 visibility: hidden 隱藏(如浮動出現的 alert 和 banner 等),如沒有隱藏,讀屏軟件仍會讀出元素內容,但屏幕外的元素通常不希望被讀出,如果不方便使用樣式進行隱藏,可以為
元素添加 aria-hidden="true" 屬性,元素則會被讀屏軟件忽略。
隱藏的內容分為兩種,一種是為了布局的需要,在條件滿足的情況下才會顯示出來;另一種是只給讀屏軟件讀的內容:有時候我們為了使讀屏軟件更准確的讀取信息,會提供一些額外的描述來達到此效果,但為了不給正常用戶帶來困擾,
這些內容對正常用戶來說是隱藏起來的。隱藏內容我們通常用 display:none 或者 visibility:hidden 來表示,但讀屏軟件同樣也會忽略這類內容。那如何隱藏內容又能使讀屏軟件讀出來呢?另外一種隱藏內容的方式是使用絕對定
位使得內容不出現在當前屏幕上,如:{position:absolute;top:-30000px;}所以在選擇使用哪種方式隱藏內容時就需要慎重考慮,display:none visibility:hidden 對任何人都是隱藏的,如果想只給讀屏軟件讀到就需要使
用上面的絕對定位方式。著作權歸作者所有。
空格的使用
我們可能會遇到一種情況例如:招商銀行卡(9326),讀屏軟件子讀屏的時候會讀為“招商銀行卡九千三百二十六”但是這個並不是盲人用戶期待聽到的,或者讀為“招商銀行卡九三四六”會更合適,所
以我們要如何處理呢?有兩種想法
第一種:將9346這幾個“數字”分別替換成“中文”,但是需要注意的就是因為銀行卡號哪個數字都有可能,所以我們需要做一個數字和中文的映射
第二種:在9326這幾個數字中間分別加一個空格,這樣因為每個數字都不挨着,中間有一個看不見的空格,所以讀屏軟件在讀屏的時候就不會讀成“九千三百二十六”而是“九三四六”
中文的使用
在某些情況下如果有些讀法不對可以替換為中文
常用場景
一、圖像的編寫
如上文所述,圖像需要補充文字描述,補充時需要使用具體的內容標題,例如書籍封面,可以使用書籍名稱,而不要直接統一描述為"書籍封面",同理用戶頭像也應該使用用戶名作為描述文字。
二、按鈕的編寫
在 H5 中,為了避免一些瀏覽器默認樣式的干擾,以及制作點擊效果(具體原因),目前采用 a 標簽實現。但從無障礙的角度考慮,a 標簽默認會被當做鏈接處理,讀屏時會讀作"鏈接內的文字 鏈接"。
-
基礎無障礙適配
需要加上 aria="button" 屬性,例如:
|
讀屏時會讀出"文字 按鈕"。
-
增加描述文字
如果 a 標簽內本身沒有文字,例如以圖片、背景色和邊框制作的按鈕,還需要加上 aria-label="描述文字",讀屏時會讀作"描述文字 按鈕"的形式。當 a 標簽內的文字對於視障人士不足以描述清楚按鈕作用時(例如需要結合上下的元
素,或者結合按鈕本身的背景圖才能理解按鈕的含義時),也可以加上 aria-label 屬性,aria-label 的內容會被優先讀出,例如:
|
讀屏時會讀出"更完整的描述 按鈕"。
-
多重標簽嵌套
另外 a 標簽內容如果有嵌套的標簽,並不會影響文字被讀出,例如:
| <a class="test_btn" role="button" href="javascript:;"> <span class="test_btn_inner"> <span class="test_btn_inner_text">文字</span> </span> </a> |
讀屏時仍會讀出"文字 按鈕"。
三、整塊可點擊元素的編寫
在遇到 banner 等本身由多個子元素組成,但點擊時為整塊點擊的元素,需要分為兩種情況考慮
-
使用 a 標簽實現
如果使用了默認的點擊效果,即使用了 a 標簽實現外層框,讀屏時子元素會被分別選中,但實際上單獨讀出每個子元素不能表達按鈕整體的完整含義。因此,我們建議整塊當作按鈕處理,但一般無需添加 aria-label,讓讀屏軟件直接
按 DOM 順序讀出子元素的文字內容即可,例如:
|
會被讀作"主標題內容文字 描述文字 提示文字 按鈕",視障人士會清楚這是整體點擊的按鈕,並且了解到其作用。如果部分內容不希望被讀出來,精簡朗讀文案的時長,例如作用不大的輔助語句,可以單獨添加 aria-hidden="true"。
需要注意,可點擊元素點擊后跳轉頁面通常采用 role="link" 聲明,而點擊后進行一些操作則通常采用 role="button" 聲明,讀屏的時候結尾分別為"鏈接"和"按鈕",但本場景下建議統一使用 role="button"或者role="text"或者role="heading",因為 role="link" 並不會讓元素整塊被識別,實際體驗上,整體識別能帶來更好的體驗,而視障人士對於"鏈接"和"按鈕"的理解包容度也比較高。但是role="button"還存在的一個問題就是在讀屏軟件最后會讀出角色"按鈕",有些場景並不適用。
-
使用語義化標簽實現
如果無需使用默認的點擊效果,建議使用語義化的標簽實現外層框,例如 section、aside,這樣用戶在使用“container 模式”進行讀屏時,元素會直接被整體識別,而不會單獨讀出子元素。
以 VoiceOver 為例,雙指旋轉可以調節焦點選擇的模式,”container 模式“下焦點僅會被 section 這類外層容器捕捉。
-
使用aria-hidden實現
如果使用了默認的點擊效果,即使用了 a 標簽實現外層框,讀屏時子元素會被分別選中,但實際上單獨讀出每個子元素不能表達按鈕整體的完整含義,所以我們可以使用aria-hidden對a標簽中的子元素進行隱藏,這樣隱藏的部分就不會獲得焦點,屏幕閱讀器就不會讀,再給a標簽添加role為button、text、heading等都可以,另外獲得焦點時讀的內容可以使用js給a標簽動態添加aria-label
|
-
實例
實例一:
| <div class="pay-total" role="text"> <strong class="JS-pay-total"> <span class="JS-pay-total-icon">¥</span> 14 <em>.22</em> </strong> </div> |
問題:ios中屏幕閱讀器將支付金額14.26分開讀,並且不讀元
原因:父元素包含很多子元素,每次都是單獨獲取,無法獲取整塊元素
調整:設置role="text"/role="heading",並將調整好的數據賦值給aria-label,並對JS-pay-total類所在的元素設置aria-hidden="true"
代碼:
| HTML: <div class="pay-total" role="text"> <strong class="JS-pay-total" aria-hidden="true"> <span class="JS-pay-total-icon">¥</span> 14 <em>.22</em> </strong> </div>
Javascript:
if (total[1].length > 1) {
total[2] = total[1].substr(1,1) == '0' ? '零' : total[1].substr(1,1);
total[3] = '';
if (total[1].length > 2) {
total[3] = total[1].substr(2,1) == '0' ? '零' : total[1].substr(2,1);
total[3] = total[3] == '2' ? '二' : total[3];
}
}
$('.pay-total').attr({
'role':'text',
'aria-label':total[0] + '點' + total[2] + ' ' + total[3] + '元'
});
|
參考
