Kris Tseng
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- slideOptions: theme: black transition: slide spotlight: enabled: false --- <style> .reveal h1 { font-size: 54px; } .reveal h2 { font-size: 46px; } .reveal h3 { font-size: 36px; } .reveal h4 { font-size: 26px; } .reveal table, .reveal p, .reveal li { font-size: 24px; } .reveal li { margin-top: 10px; margin-bottom: 10px; font-size: 20px; } .reveal blockquote { font-style: normal; text-align: left; padding-left: 36px; padding-right: 36px; } .reveal blockquote, .reveal blockquote p { font-size: 20px; } </style> # Accessibility Testing: Screen Readers Kris Tseng 2020/11/19 --- ## 螢幕閱讀器基本介紹 ---- ### 什麼是螢幕閱讀器 > 螢幕閱讀器主要的功能,是將數位內容轉換成 **語音** 或是 **點字**,全功能的螢幕閱讀器可以讀取到作業系統、應用程式和網站的介面和內容。 ![](https://i.imgur.com/YBwYnww.png =x200)![](https://i.imgur.com/wzAvEEG.png =x200) > 螢幕閱讀器並不能自動讓我們的網頁加上無障礙功能,而是需要在網頁設計開發的時候,遵循 W3C 的 Web Content Accessibility Guidelines (WCAG) 2.0,讓網頁相容於螢幕閱讀器。 ---- ### 什麼樣的使用者 使用螢幕閱讀器 > - **失明**:失明人士是螢幕閱讀器主要使用者,其中包含全盲和部分視力喪失。 > - **失明且失聰**:使用螢幕閱讀器搭配點字機。 > - **低視能/弱視**:對於螢幕放大軟體功能不足以看清楚螢幕的使用者,會搭配螢幕閱讀器提供語音內容。 > - **閱讀/認知障礙**:對於閱讀和認知障礙人士來說,語音會比文字更容易理解。 > - **不便使用眼/手的情境**:使用者無論有無殘疾,也有可能在不便使用眼和手的情境使用螢幕閱讀器。 ---- ### 已經有自動化的無障礙測試工具了 ### 為什麼需要使用螢幕閱讀器作測試 ? 1. 最重要的原因是,就算網頁已經加上無障礙功能,但實際上使用者都還是需要透過螢幕閱讀器,才能讀取網頁的內容。 2. 無障礙自動化測試工具沒辦法找出無障礙相關的全部問題,常見的種類包括: - 品質和正確性:自動化測試只能找出 `<img>` 少了 alt 屬性,但沒辦法驗證 alt 文字的正確性。 - 鍵盤和焦點的行為模式:自動化測試很難判斷互動行為的焦點位置是否合適。 - 客製的元件:特別是使用 JavaScript 製作的元件種類繁多,使用螢幕閱讀器是唯一可以測試是否相容無障礙的方式。 ---- ### 螢幕閱讀器與瀏覽器的組合 [WebAIM 螢幕閱讀器使用者調查](https://webaim.org/projects/screenreadersurvey8/) ![](https://i.imgur.com/AqqtK9S.png =x250)![](https://i.imgur.com/mdO83ZN.png =x250) > - 對於大部分的靜態網頁來說,使用一組螢幕閱讀器跟瀏覽器組合已經足夠測試及修復無障礙相關問題。 > - 但對於動態或是互動性高的內容(例如:JavaScript 元件、表單),螢幕閱讀器跟瀏覽器間細微差異可能造成問題,建議使用多種組合來測試。 ---- ### 行動裝置 ![](https://i.imgur.com/VR9NgM3.png =x250)![](https://i.imgur.com/9iWGFCC.png =x250) > VoiceOver 比 TalkBack 提供更多無障礙功能,但在兩個平台上作測試同等重要。 ---- ### 是否可以偵測使用者正在使用螢幕閱讀器? - 就技術上來說,螢幕閱讀器不是瀏覽器,不直接與伺服器互動。因此很難偵測到正在使用螢幕閱讀器。 - 如果真的可以偵測到螢幕閱讀器的使用,會有幾個疑慮: - 會將無障礙與一般網頁分流,造成無障礙與一般網頁功能相異。 - 多版本的網頁維護不易,特別是無障礙網頁較一般網頁需要更高維護成本,擔心因此而選擇不被更新維護。 - 無障礙網頁屬於小眾使用者,可能會因為商業考量而被捨棄。 ---- 如果要在 Mac 上使用 JAWS/NVDA 作測試時, 遇到的問題通常是缺少了 Insert 鍵,這裡提供了幾個方式解決: 1. 外接鍵盤 2. SharpKeys - 在 windows 裡使用 key mapping 3. Karabiner Elements - 使用 touch bar 模擬 *要在 mac 上使用 NVDA / JAWS 做測試,需要安裝 windows 虛擬機 --- ## 螢幕閱讀器使用上的特點 ---- ### 開啟之後沒有圖像化介面 > 螢幕閱讀器被開啟後,會在背景運行,使用者操作應用程式時,提供語音朗讀。 ![](https://i.imgur.com/4USPJ1X.png =x250) > 某些螢幕閱讀器有提供正在唸的內容大綱或是字幕的功能 ---- ### 不使用滑鼠 一切都靠鍵盤 > 受限於視力障礙,大部分視障人士僅使用鍵盤而不是滑鼠,因此內容需要為鍵盤優化: > > - 所有控制項應可以透過 tab 鍵導航 (連結、按鍵、表單元素等)。 > - 連結、按鈕應可以透過 enter 或是 space 鍵啟動。 > - 滑鼠的 hover 功能需要有相對應的按鍵事件。 > - 在畫面上被隱藏的項目(如:未被點開的下拉選單),不應當被 tab 鍵選取得到。 > - 當對話框被開啟時,鍵盤焦點應移至對話框元件上;當對話框關閉時,焦點應回到原先開啟它的控制項(或是適當的位置)。 > - JavaScript widget 應該遵循 W3C 的 [ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/) 的鍵盤操作行為規範。 > - 頁面上不應該出現任何困住使用者鍵盤導航的陷阱。 > - 使用 tab 遍歷所有控制項的順序必須是合理的。 ---- ### 對螢幕閱讀器來說 網頁是線性內容 ![](https://i.imgur.com/LQrFp5k.png =x350) > - 使用螢幕閱讀器唸出整個網頁時,會從 DOM 的第一個元件開始,一直進行到最後一個元件,如同電話語音系統。 > - 螢幕閱讀器會忽略使用 css ,改變元件在畫面上的位置,而僅會依照 DOM 上的順序尋找元件。 > - 我們需要確認 DOM 元件順序,無論是在一般顯示、拿掉樣式,或是透過螢幕閱讀器朗讀時,都應具合理性。 ---- ### 非線性導航 雖然對螢幕閱讀器來說網頁內容都是線性連貫的, 但提供快捷鍵或是類似的功能,讓焦點可以跳至指定元件, 如:landmarks、headings、links、tables、form elements、 graphics、list items、iframes 等。 而使用者可以使用這樣方式的前提是, 網頁內容有正確地使用語意化標籤設計開發。 ---- ### 視覺樣式會被忽略 > 某些螢幕閱讀器可以設定讓某些樣式被傳達。但對使用者來說,大部分的 css 是會被忽略的,例如:顏色、背景圖片、字體樣式、粗體、斜體、文字大小、大小寫(除非使用者使用逐字朗讀)、項目之間的空格/空行、元件位置的改變。 > 如果使用的 css 帶有重要語意時,也應該使用文字標示同等意思。例如:使用背景色標示重點的文字,可以加上前綴 important: 字樣。 > 唯一會影響 screen reader 的 css 是 `display: none`,screen reader 會略過所有標示 `display: none` 的元件。 ---- ### 標點符號 > - 不同廠牌的螢幕閱讀器對標點符號處理方式不盡相同,對於 `-` `;` `(` `)` 這幾個符號來說,差異性較高,一般來說 JAWS 會唸出較多的標點符號,而 VoiceOver 則較少。 > - 遇到逗號、句號,大部分螢幕閱讀器只會像一般人說話那樣停頓。 > - 大多數螢幕閱讀器有提供設定,讓使用者可以變更標點符號被念出的數量多寡。 ---- 以下是相對安全的符號: <style> th:nth-child(3), td:nth-child(3) { border-right: 1px solid white; } </style> <table> <thead> <tr> <th>符號</th><th>英文環境</th><th>中文環境</th> <th>符號</th><th>英文環境</th><th>中文環境</th> </tr> </thead> <tbody> <tr> <td>@</td><td>the at symbol</td><td>小老鼠</td> <td>€</td><td>Euro</td><td>歐元</td> </tr> <tr> <td>&</td><td>ampersand</td><td>and</td> <td>£</td><td>British</td><td>英鎊</td> </tr> <tr> <td>/</td><td>slash</td><td> </td> <td>¥</td><td>Yen</td><td>人民幣</td> </tr> <tr> <td>©</td><td>copyright</td><td> </td> <td>%</td><td>percent</td><td> </td> </tr> <tr> <td>®</td><td>registered</td><td>註冊商標</td> <td>½</td><td>one half</td><td>二分之一</td> </tr> <tr> <td>™</td><td>trademark</td><td>商標</td> <td>¼</td><td>one fourth</td><td>四分之一</td> </tr> <tr> <td>¶</td><td>paragraph</td><td> </td> <td>¾</td><td>three fourths</td><td>四分之三</td> </tr> <tr> <td>•</td><td>bullet</td><td> </td> <td>°</td><td>degrees</td><td>度</td> </tr> <tr> <td>$</td><td>dollar</td><td>錢</td> <td></td><td></td><td></td> </tr> </tbody> </table> ---- ### 縮寫 螢幕閱讀器遇到縮寫的時候,有兩種處理方式: > A.當縮寫中有足夠的母音和子音,螢幕閱讀器會嘗試當作單字發音,例如: NASA;當使用者不能理解這個單字時,可以讓螢幕閱讀器逐字朗讀 > B.如果不能當單字念出來的字,則會依序唸出字母,如:DHS。(逐字朗讀時,螢幕閱讀器會用較高且大聲的方式強調大寫字母) ---- ### 使用縮寫的優化 > - **我們可以在縮寫第一次出現的時候解釋他** > 例如: A Registered Retirement Savings Plan (RRSP) is a government-regulated investment account with special tax benefits to help you maximize your retirement savings. > - **利用 `<abbr>` 標示** > `<abbr title="Self-Contained Underwater Breathing Apparatus">SCUBA</abbr>` > 螢幕閱讀器會為使用者唸出此縮寫展開的文字。 ---- ### 透過 Accessibility API 讀取瀏覽器解析內容 > 螢幕閱讀器不會直接讀取網頁的程式碼,而是透過 Accessibility API 讀取瀏覽器解析 JavaScript 及樣式後的內容 > 話雖如此,螢幕閱讀器仍沒辦法應付太過複雜的動態內容。 > 螢幕瀏覽器只會唸出焦點所及的 DOM 物件當前的內容,對於網頁上其他位置的動態效果,螢幕瀏覽器沒有辦法讓使用者即時知道。 > 例如:在焦點外的文字 "Hello World" ,動態改變成 "Hello Universe",螢幕閱讀器只會在焦點移到該元件時,唸出改變之後的 "Hello Universe",而無法讓使用者知道這裡曾經是 "Hello World" ---- ### 虛擬緩衝區 (Virtual Buffer) > 為了讓使用者可以透過指令在網頁內容中快速地導航,螢幕閱讀器會先將整個網頁的資料結構暫存在記憶體中。 > 將內容暫存至 virtual buffer 耗費的時間通常很短暫,但是也有可能會因為這個延遲而影響正確性,而這個情況在面對動態內容特別顯著,特別是使用 ajax 取得的動態內容。 > 解決方案是在 ajax 取得回應後,設定一定時間的延遲,再將焦點指向取回內容的位置,以避免螢幕閱讀器取到空白或是錯誤的內容,對於桌機通常 0.5 ~ 1 秒的延遲較適當,而行動裝置則推薦 2 秒左右。 --- ## Accessibility APIs ---- ### Windows accessibility API 目前在 Windows 上使用的 accessibility API 是 Microsoft UI Automation 和 Microsoft Active Accessibility (MSAA) Edge browser 和 Narrator 使用的是 Microsoft UI Automation; 而 MSAA 則使用在 IE 上 ---- [Windows 10 SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk/) 提供了檢查 accessibility 資訊的工具程式 Inspect.exe 安裝 Windows 10 SDK 後,Inspect.exe 會出現在 `Program Files > Windows Kits > 10 > bin > [your platform]` 資料夾內 <img src="https://dequeuniversity.com/assets/images/module-using-screen-readers/ui-automation-inspect.png" height="450px" /> ---- ### MacOS MacOS 始自 v10.2 開始加入 accessibility API。 在 Apple 的集成開發者工具 Xcode 中, 也有提供檢查 accessibility 資訊的工具 Accessibility Inspector 在安裝 Xcode 後,選取主選單 `XCode > Open Developer Tool > Accessibility Inspector` <img src="https://dequeuniversity.com/assets/images/module-using-screen-readers/xcode-a11y-inspector.png" height="350px" /> ---- ### 瀏覽器的 accessibility 架構 > 瀏覽器會建構近似 DOM tree 結構的 accessibility tree,但因為不是每個 DOM 元素都帶有語意,例如: `<div>` `<span>` 等標籤,就不會建構在 accessibility tree > 換句話說,像是 heading、table、list、landmark、link 等,帶語意的標籤都會被建構在 accessibility tree ---- ### Browser Accessibility Tree 帶有的資訊: | | | | -------- | -------- | | Name | 通常會是包含在元件內的文字,如同在 link 或是 heading 中的文字,而某些元件需要用特定 html 元件或是 aria 屬性來指定。例如:表單元件可以用 `<label>` / `aria-label` / `aria-labelledby` | | Description | 來自 `aria-describedby` 或是 `title` | | Role | 原生 HTML 元件的語意,或是來自 ARIA 的 role 屬性 | | Property | 元件的特色,如 `haspopup="true"` | | Relationship | - 元件特定的階層結構,如 `<li>` 一定會屬於 `<ul>` 或 `<ol>` 的子層 <br> - 用 ARIA 連結的元件關係 `aria-owns="someID"` / `aria-controls="someID"` | | State | 元件目前狀態,如:`aria-selected="true"` | ---- 瀏覽器的 dev tool 有提供查看 accessibility tree 的功能, 可以在 dev tool 的 Element tab 中的 Accessibility 畫面中,查看選取元素的相關資訊 <!-- <img src="https://dequeuniversity.com/assets/images/module-using-screen-readers/edge-f12-a11y-tree.png" height="350px" /> --> ![](https://i.imgur.com/RIGgaW0.png =x450) --- ## 尋路/導視 (Wayfinding) > 初次使用螢幕閱讀器的人,可能會覺得在測試時需要聽完整個網頁內容。但事實上熟練的螢幕閱讀器使用者,會用更有效率的方式導航,並找到頁面的資訊。 > 這個章節提供了一些螢幕閱讀器使用者常用的,一些找到想要的資訊的方式。 ---- ### Title ![](https://i.imgur.com/BteBpg6.png) - title 會是使用者最先取得的網頁資訊 - 當瀏覽器存在多個頁面時,使用者依據 title 選擇想要讀取的頁面 - 如果頁面沒有具描述性的 title 時,使用者會被迫需要讀取更多內容,才能知道這個頁面是不是他們要的 - 通常螢幕閱讀器會在網頁載入的時候,先唸出頁面的 title;某些螢幕閱讀器也會唸出其他頁面資訊,像是有多少 headings、landmarks、連結和表單元件 - 網頁的 title 和主標題有一樣的功能,螢幕閱讀器的使用者通常期待兩者會是相同的;如果兩者相異,會讓使用者感到困惑 ---- ### 依序唸出完整網頁內容 > 當一開啟螢幕閱讀器或是新開網頁時,螢幕閱讀器會自動將網頁完整唸出,依序是 > 1. 頁面的 title > 2. 頁面上主要功能的概要 > 3. 接著才是從頭自尾的完整內容 ---- 如果在過程中讓螢幕閱讀器暫停,也可以使用快捷鍵從目前位置繼續 > - JAWS Insert + Down > - NVDA Insert + Down > - VoiceOver Control + Option + A ---- ## Headings > Headings 讓螢幕閱讀器的使用者可以快速了解網頁資訊,而不需要讀取全部的內容。 > 螢幕閱讀器也提供了讓使用者快速取得 headings 資訊的方式 ---- ### 1. 列出全部的 headings | | | | | -------- | -------- | -------- | | JAWS | Insert + F6 | heading list | | NVDA | Insert + F7 | open element list then select headings | | VoiceOver on macOS | Control + Option + U | open rotor then select headings ![](https://i.imgur.com/RL97FT9.png =x250)<img src="https://i.imgur.com/9qMK32p.png" height="250px" />![](https://i.imgur.com/RRC2Tq6.png =x250) JAWS heading list / NVDA 元件清單 / VoiceOver Rotor ---- ### 2. 跳至下一 heading | | | | -------- | -------- | | JAWS | H | | NVDA | H | | VoiceOver on macOS | Control + Option + Command + H | [NVDA next heading video ](https://media.dequeuniversity.com/courses/generic/testing-screen-readers/2.0/en/videos/nvda/headings_nvda.mp4) ---- ### 3. 跳至下一特定層級的 heading | | | | -------- | -------- | | JAWS | 1 ~ 6 | | NVDA | 1 ~ 6 | ---- ## Landmarks Landmarks 讓使用者可以快速導航至 主要內容、導航區、header、footer、banner 等特定區塊 landmarks 也是讓使用者快速了解網頁主要內容的方式之一 ---- ### 1. 列出全部的 landmarks | | | | | -------- | -------- | -------- | | JAWS | Insert + F3 | open elements List then select landmarks | | NVDA | Insert + F7 | open elements List then select landmarks | | VoiceOver on macOS | Control + Option + U | open rotor then select landmarks | [VoiceOver landmarklist vedio](https://media.dequeuniversity.com/courses/generic/testing-screen-readers/2.0/en/videos/voiceover/landmarks_voiceover.mp4) ---- ### 2. 跳至下一 landmark | | | | -------- | -------- | | JAWS 16 以上 | R | | JAWS 15 以下 | ; | | NVDA | D | | VoiceOver on macOS | Control + Option + Command + H | [NVDA next landmark video](https://media.dequeuniversity.com/courses/generic/testing-screen-readers/2.0/en/videos/nvda/landmarks_nvda.mp4) > JAWS 還提供了跳至主要內容 landmark 的快捷鍵: Q > ---- ## Lists 螢幕閱讀器讀取到列表時,會先唸出列表種類和列表選項數量, ![](https://i.imgur.com/PBQEk04.png) 例如:"Bulleted list with 5 items" 僅 JAWS 提供了列出全部列表的功能: Insert + Ctrl + L ---- ### 跳至下一列表 | | | | -------- | -------- | | JAWS | L | | NVDA | L | | VoiceOver on macOS | Control + Option + Command + X | ---- ## 導航至鄰近元件 除了讓唸完整個網頁和跳至特定元件的方式之外 螢幕閱讀器也提供了線性移動焦點的功能 ---- ### 1. 從目前位置繼續往下唸 | | | | -------- | -------- | | JAWS | Insert + Down | | NVDA | Insert + Down或Numpad + | | VoiceOver on macOS | Control + Option + A | ---- ### 2. 上/下一行 | | | | -------- | -------- | | JAWS | Up / Down | | NVDA | Up / Down 或 Numpad 7 / Numpad 9 | | VoiceOver on macOS | Control + Option + Left / Right | <!-- ---- ### 3. 上/下一句 | | | | -------- | -------- | | JAWS | Alt + Up / Down | | NVDA | Alt + Up / Down | | VoiceOver on macOS | Control + Option + S (read sentence) | Note: 此功能在 NVDA 上沒有成功過 --> ---- ### 上/下一項的補充說明 > 在使用 Up / Down 導航時,會發現 NVDA/JAWS 在句子不完整的位置斷句,這是因為 NVDA/JAWS 為了內部緩存的原因做了分段。 > VoiceOver 對於元件分類顯得更邏輯化,因此在使用 Control + Option + Right/Left 導航時,大多會正確停在完整句子結尾。 ---- ### 使用 tab 鍵 > 使用 Tab 是最快可以導航至可操作元件的方式之一,Shift + Tab 可以回到上一個可操作元件, 可操作元件包括: > - 連結 > - 表單元件 > - ARIA 元件 > - 標示 tabindex="0" 的元件 [NVDA Tabbing Video](https://dequeuniversity.com/assets/video/screen_readers/nvda/tabbing_nvda.mp4) > 因為這個方式會掠過網頁大部分的內容,所以請確認連結的文字或是表單的 label,有助於幫助使用者理解。 > 例如:連結或是 label 的文字使用 more、read more 或是 click here 等,沒有辦法幫助使用者更了解內容 ---- #### 行動裝置上的相似功能 > 在行動裝置上與 Tab 導航相似的功能,是在 iOS 上的 Rotor 選單,在 Rotor 可以選擇 連結 / 表單元件後,以手指上下滑動,焦點會跳至相鄰的同類元件。 > 開啟 Rotor 的方式,是以兩指在畫面上旋轉,如同轉動旋鈕 <img src="https://i.imgur.com/lqRSGyI.png" height="350px" /> ---- ## 圖片 螢幕閱讀器在處理圖片,分為以下幾種狀況: | | | | -------- | -------- | | 有 alt 屬性值 | `<img src="cat_0123.jpg" alt="A tabby cat">`<br>會唸出 "Graphic, a tabby cat<br>*不必在 alt 文字前加上 image of 或是 graphic | | 沒有 alt 屬性 | JAWS 會直接唸出圖片檔名 | | 有 alt 屬性,但沒有值 | `<img src="cat.jpg" alt="">`<br>螢幕閱讀器會略過這樣的圖片標籤 | | 帶連結的圖片 | 會先念出 "link graphic",在接著 alt 文字 | 沒有 alt 的帶連結圖片 | 會以連結的目標網址代替<br>`<a href="cat_page.html"><img src="cat_0123.jpg" alt=""></a>`<br>以 JAWS 為例,會唸出:"Link graphic, cat underscore page dot H T M L" | ---- ### 1. 列出全部的圖片 > | | | > | -------- | -------- | > | JAWS | Insert + Ctrl + G | > | VoiceOver on macOS | open rotor then select images | ### 2. 跳至下一張圖片 > | | | > | -------- | -------- | > | JAWS | G | > | NVDA | G | > | VoiceOver on macOS | Control + Option + Command + G | ---- ## 連結 > 螢幕閱讀器會前綴 "link",接著念出連結中的文字;某些螢幕閱讀器對於已訪問的連結,會前綴 "visited link" ---- ### 對於連結文字的優化 > - 連結一定要包含文字:如果連結中只包含非文字項目,請用 ARIA 屬性加上描述性文字,或是利用 css 的方式將文字隱藏。 > - 需具描述性:避免使用 click here、here、more、read more 之類的文字。 > - 不須加上 "link" 前綴。 > - 連結文字要具一致性:如果同一頁面上兩個連結都連至同一目標網址,請給他們同樣的文字。 ---- ### 1. 列出全部的連結 | | | | -------- | -------- | | JAWS | Insert + F7 | | NVDA | open element list then select links | | VoiceOver on macOS | open rotor then select links | ![](https://i.imgur.com/658x75d.png) JAWS Links List ---- ### 2. 跳至下一連結 | | | | -------- | -------- | | JAWS | N/A | | NVDA | K | | VoiceOver on macOS | Control + Option + Command + L | ---- ### 3. 跳至下一未/已訪問連結 | | 未訪問 | 已訪問 | | -------- | -------- | ------- | | JAWS | U | V | | NVDA | U | V | | VoiceOver on macOS | N/A | Control + Option + Command + V | ---- ## 表格 > 螢幕閱讀器會在唸出 table 後提示使用者該表格行列的數量,例如: "Table with 4 columns and 5 rows." > 使用者可以依此決定是否繼續唸完全部的表格欄位,或是手動移動至特定欄位 [NVDA table video](http://www.youtube.com/watch?v=1OmLVMijotA&t=6m38s) ---- ### 1. 列出全部表格 | | | | -------- | -------- | | JAWS | Insert + F3 (open element list then select table) | | NVDA | N/A | | VoiceOver on macOS | open rotor then select tables | ---- ### 2. 跳至下一表格 | | | | -------- | -------- | | JAWS | T | | NVDA | T | | VoiceOver on macOS | Control + Option + Command + T | ---- ### 3. 表格內欄位移動 | | | | -------- | -------- | | JAWS | Control + Alt + Arrow keys | | NVDA | Control + Alt + Arrow keys | | VoiceOver on macOS | Control + Option + Arrow keys | [Table nav video](https://dequeuniversity.com/class/screenreaders2/wayfinding-reading-content/tables) ---- ## 頁面內搜尋 > 有時候使用者很難用螢幕閱讀器找到想要的資訊,可以使用頁面搜尋。螢幕閱讀器會唸出搜尋結果數量,如:第一個結果,共三個。 | | | | -------- | -------- | | JAWS | Control + F | | NVDA | Control + F | | VoiceOver on macOS | Control + Option + F | ![](https://i.imgur.com/WIuPLqH.png =x250) ---- ## 表單 > JAWS / NVDA 提供 focus mode (form mode) 以在表單元件內操作時,以使用表單專用的快捷鍵 (某些會複寫主要的快捷鍵) > | | Enter form mode | Exit form mode | | -------- | -------- | -------- | | JAWS | Enter key (當焦點在表單元件時) | Numpad Plus | | NVDA | Insert + Space | Insert + Space | ---- ### 列出全部表單元件 | | | | -------- | -------- | | JAWS | Insert + F5 | | NVDA | Insert + F5 | | VoiceOver on macOS | N/A | ---- ### JAWS / NVDA 表單快捷鍵 | | 下一表單元件 | 選擇/取消 | 下一按鍵 | 下一 checkbox | 下一下拉選單 | 開啟下拉選單 | 下一 radio | 選取/取消 radio | | -------- | -------- | --------- | ------- | --------| ------| ------ | ---- | ---- | | JAWS | F | Space / Enter | B | X | C | Alt + Down | A | Up/Down | | NVDA | F | Space | B | X | C | Alt + Down | R | Up/Down | --- ## Screen Reader Modes > 螢幕閱讀器為了應付不同使用情境,提供了不同的鍵盤配置模式,大致可以分為以下兩大類: > - 頁面導航模式 (Page Navigation):又常被稱作 scan mode(Narrator)、browse mode、document mode > - 輸入/互動模式 (Input or Interaction):包括:forms mode、focus mode、application mode ---- ### Document/Browse/Scan Mode > - 螢幕閱讀器的預設模式,主要用於導覽及閱讀具語意的元件,在此模式中,大部分的鍵盤點擊都被設定為導航行為的快捷鍵,例如: 點擊 H 會跳至下一個 heading 元件 > - 當焦點從互動元件上離開時,JAWS/NVDA 應會自動將互動模式切換成導覽模式;若沒有,可使用以下快捷鍵 > - VoiceOver 沒有類似的模式切換概念 | | | | | -------- | -------- | -------- | | JAWS | Enter/ Numpad Plus | form / browse mode | | NVDA | Insert + Space | focus / document mode | ---- ### Focus / Application mode > - 當焦點進入帶有 role="application" 的元件時,會自動切換成 Application mode。 > - 在 Application mode 時,螢幕閱讀器會關閉大部分的鍵盤快捷鍵,讓開發者可以實作的鍵盤功能不受影響。使用者也因此無法用快捷鍵導航至其他語意化元件,請謹慎使用。 > - 在互動區塊(form or role="application")內的文字,除了可以被 tab 的元件外,很容易被使用者略過或是讀取不到,有兩種方式可以優化: > - 將文字用 aria 屬性關聯至可被 focus 的元件 (使用 aria-label 或 aria-describedby) > - 將不可被 focus 的文字包在帶 role="document" 的元件內 ---- ### Forms Mode > - 使用者使用表單時,可能希望可以編輯文字,因此螢幕閱讀器也會關閉與字母、數字相關的快捷鍵。 > - 當焦點移至表單欄位時,會自動切換成 form mode。(焦點在 `<form>` 不會觸發 form mode) > - 在表單中,使用者常用 tab 導航,因此不可被 focus 的文字常被忽略。 ---- 在 form mode 時,以下的表單文字會被螢幕閱讀器唸出: > - 使用 `<label>` 的表單標題文字 > - 使用 aria-label 的表單標題文字 > - 使用 aria-labelledby 的表單標題文字 > - 使用 aria-describedby 關聯表單欄位的文字 (在 Mac 的 VoiceOver 上會有一段長延遲) > - 在 `<fieldset>` 使用 `<legend>` 的文字 > - 連結中的文字 > - 帶有 `tabindex="0"` 元件中的文字 ---- ## Table Mode > - 當焦點在表格內的儲存格移動時,螢幕閱讀器會先唸出該儲存格對應的標頭。 > - 通常螢幕閱讀器只會唸出新出現的標頭資訊,例如,在同一行移動時,只會在第一個儲存格前唸出左邊的行標頭 (row header),之後只會先唸上方的列標 (column header)。 > - 如果螢幕閱讀器只有唸出欄位值而沒有先唸 header 時,有可能是表格結構不正確 ![](https://i.imgur.com/7n8xeYd.png =x200) [VoiceOver table cell nav video](https://media.dequeuniversity.com/courses/generic/testing-screen-readers/2.0/en/videos/voiceover/groupedheaders_voiceover.mp4) ---- ## JAWS Cursors > JAWS 提供三種用鍵盤游標模式 > - PC Cursor:Numpad Plus > 等同鍵盤輸入時,垂直閃動直線的游標狀態。 > - JAWS Cursor:Numpad minus > 模擬滑鼠游標,指向正在焦點上的元件,可以用鍵盤方向鍵移動。 > http://www.youtube.com/watch?v=LAXQ7qVW4PI&t=7m34s > - Virtual PC Cursor:在網頁預設開啟的游標狀態 > 與 PC Cursor 相似,Virtual PC Cursor 使用 Shift + Arrow Keys 選取唯讀的文字。 > --- ## NVDA on Windows > - 推薦的組合是 NVDA + Chrome 或是 Firefox ---- ### 基本快捷鍵 > NVDA 主要的功能鍵是 Insert,但也可以改設定為 Caps Lock | | | | -------- | -------- | | 啟用 | Ctrl + Alt + N | | 結束 | Insert + Q | | 從目前位置往下唸 | Insert + Down | | 暫停唸出目前句子 | Ctrl | | 上/下一項 | Up/Down | | 開啟連結 | Enter | | 點擊按鍵 | Enter or Space | ---- ### 快速導航 | 跳至下一項 | | | -------- | -------- | | 可 focus 的元素 | Tab | | Heading | H | | 指定級數的 Heading | 1 ~ 6 | | Landmark | D | | 連結 | K | | 已訪問過的連結 | V | | 表單項目 | F | | 表格 | T | | 列表 | L | | 圖片 | G | | 按鍵 | B | > 以上快捷鍵都可以加上 Shift 作為反向 ---- ### 表單 | | | | -------- | -------- | | 列出全部表單元件 | Insert + F7 | | 下一表單欄位 | F | | 下一按鍵 | B | | 下一 checkbox | X | | checkbox 選取/取消 | Space | | 下一下拉選單 | C | | 下拉選單選項選擇 | Down | | 下拉選單選項多選 | Shift + Up/Down | | 下一 radio | R | | 切換 radio | Up/Down | | 切換 Browse/Focus mode | Insert + Space | > 當焦點進入可互動元件時,會自動切換 Browse / Focus mode,或者使用者可以使用快捷鍵切換 ---- ### 元件清單 > Insert + F7 <img src="https://i.imgur.com/I3VIxNc.png" height="400px" /> ---- ### NVDA 額外的設定 > 開啟/關閉滑鼠焦點: Insert + M > 檢視報讀內容 (Speech Viewer) :狀態列 NVDA icon -> 工具 -> 檢視報讀內容 ![](https://i.imgur.com/rn2ikJt.png =x350) ---- > 啟用醒目提示框 ![](https://i.imgur.com/jVhf5h5.png =x400) ---- ### NVDA Resource [NVDA Quick Reference Guide](https://dequeuniversity.com/assets/pdf/screenreaders/nvda-guide.pdf) [NVDA User Guide](https://www.nvaccess.org/files/nvda/documentation/userGuide.html) --- ## VoiceOver on MacOS ---- ## 前置設定 > 預設鍵盤輔助功能只能 tab 到表單元件,需要 tab 到連結或是其他元件時,需要開啟設定 > System Preferences > Keyboard > Shortcuts > Full Keyboard Access > All controls ![](https://i.imgur.com/BSrRwIJ.png =x250) > 啟用 Safari 焦點黑框: > Safari -> 偏好設定 -> 進階 -> 按下 Tab 鍵來特別標明 ---- ## 基本快捷鍵 > VoiceOver 主要功能鍵 VO = Control + Option | | | | -------- | -------- | | 啟用/關閉旁白 | Command + F5 | | 開啟轉輪 | VO + U | 從目前位置往下唸 | VO + A | | 暫停唸出目前句子 | Control | | 前一項 / 後一項 | VO + Left / Right | 頁首 / 頁尾 | VO + Fn + Left / Right | | 進入下一層 / 上一層 | VO + Shift + Down / Up | | 啟用連結或是表單控制項 | VO + Space (Enter) | ---- ## 快速導航 | 跳至下一項 | | | -------- | -------- | | 可 focus 的元素 | Tab | | 連結 | VO + Command + L | | 已訪問過的連結 | VO + Command + V | | 標題 | VO + Command + H | | 表單項目 | VO + Command + J | | 表格 | VO + Command + T | | 列表 | VO + Command + X | | 圖片 | VO + Command + G | > 以上快捷鍵都可以加上 Shift 作為反向 ---- ## 功能轉輪 (Rotor) Rotor 提供快速導航到常用元件的方式 | 功能 | 快捷鍵 | | -------- | -------- | | 開啟 Rotor | VO + U | | 離開 Rotor | Esc | | 切換分類 | Left / Right | | 切換選取項目 | Up / Down | | 啟用項目 | Enter | ---- ### VoiceOver 額外設定 > - 關閉滑鼠焦點:開啟工具選項 (Control + Option + F8),在 Mouse cursor 勾選 Ignores VoiceOver cursor ---- ### macOS 輔助使用快速鍵 [VoiceOver Quick Reference Guide](https://dequeuniversity.com/assets/pdf/screenreaders/voiceover-macos-guide.pdf) [VoiceOver 使用手冊](https://support.apple.com/zh-tw/guide/voiceover/welcome/10) --- ## ChromeVox > ChromeVox 是內建在 Chrome Browser 在 Chrome 瀏覽器內的螢幕閱讀器,不向其他全功能的螢幕閱讀器, ChromeVox 只能讀出 Chrome 內的內容。 > 雖然對於實際使用者並不普及,但測試靜態網頁內容 ChromeVox 不失是個不錯的工具。 [ChromeVox demo video](https://dequeuniversity.com/assets/video/module-screenreaders/chromevox.mp4)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully