iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 13
2
Modern Web

實踐無障礙網頁設計(Web Accessibility)系列 第 13

實作無障礙網頁功能:當使用者輸入錯誤的警告視窗 Alert

這系列無障礙的鐵人賽文章,實踐的內容主要是根據 W3C:WAI-ARIA 的實踐,從設計模式及組件(Design Patterns and Widgets)裡面挑選最想嘗試的,如果有朋友想瞭解全部 Widget 該怎麼實作及其規範,歡迎自行爬規範內容,也許我們可以討論一下;若以下文章內容理解有任何錯誤,請多指教~

(圖片來源:unsplash

警報 Alert(打開文件

3.2 Alert
An alert is an element that displays a brief, important message in a way that attracts the user's attention without interrupting the user's task. Dynamically rendered alerts are automatically announced by most screen readers, and in some operating systems, they may trigger an alert sound.

網頁除了傳達資訊以外,最常做的事情就是讓使用者能與網頁互動,情境像是:提供註冊表單讓使用者填寫、遊戲需要完成特定任務才能破關之類的。在使用者操作錯誤時,我們會適時提供明確的錯誤提示,讓他知道下一步該做些什麼。

在提示訊息的「容器」上,新增 role 屬性,值是 alert。螢幕閱讀器在瀏覽頁面時,永遠只會有一個焦點,而 alert 的行為表現是,幫你朗讀即時顯示的提示內容,而不影響也不變換螢幕閱讀器的焦點,若是 Audio UI 還正在朗讀其他焦點的內容,也會立即中斷後念出 alert。換句話說,就是你也不該讓使用者需要主動「關閉」它,如果你需要使用者操作才能關閉它,那麼應該使用另一個角色 alertdialog,不涵蓋在今天的實踐範圍唷。

要注意的地方

  • 設計自動的消失機制:
    • 顯示的提示內容也要考量到成功原則 2.2.3 No Timing,別消失得太快,會造成每個人理解程度不一,有些使用者會來不及瞭解「剛剛發生什麼事?」。
  • 出現機率也不能太頻繁:
    • 這個有很大程度較難達成,但為了某部分具有認知障礙的人們,還是可以參考一下成功原則 2.2.4 Interruptions

在實際情境中,也很適合拿來作為 data filter 的提示,有一個輸入框。


鍵盤的可訪問性

  • alert 角色,不需要支援鍵盤的操作。

Roles、States、Properties

  • 當設定角色是 alert 時,會隱含 ARIA 屬性預設值:
    • aria-live:預設為 assertive
      • aria-live 提供三個值,分別是 off、assertive、polite,差別在於 polite 在提醒的重要程度沒有 assertive 高,螢幕閱讀器也不會打斷使用者原本正在聆聽的內容。
    • aria-atomic:預設為 true

實踐開始囉!

想做一個輸入手機號碼的錯誤提示。

希望能做到:

  • [x] 支援螢幕閱讀器

HTML

<!-- 提示區域 -->
<div id="alert" class="alert"></div>

<!-- UI -->
<form class="form flex-margin-auto">
    <fieldset class="form__field">
        <label for="cellphone-input" class="form__field__label">手機號碼</label>
        <input type="tel" placeholder="請輸入你的手機號碼" id="cellphone-input" aria-describedby="cellphone-format" class="form__field__input" value="0980218888"/>
        <span id="cellphone-format" class="form__field__description">電話號碼格式:0980218888</span>
    </fieldset>
    <div class="form__validation">
        <button type="button" id="check-button">點我驗證</button>
    </div>
</form>

CSS

body {
    display: flex;
    justify-content: center;
    align-content: center;
    height: 100vh;
}

.form {
    min-width: 400px;
    box-sizing: border-box;
    padding: 30px;
    border-radius: 5px;
    background: #eee;
    box-shadow: 0 10px 20px -8px #ccc;
    flex-wrap: wrap;
    
    &__field {
        flex-basis: 100%;

        &__label {
            line-height: 2;
            font-size: 1.2rem;
            font-weight: bold;
            margin-right: 10px;
        }

        &__input {
            padding: 0.5rem 10px;
            border-radius: 5px;
            border: 1px solid #ccc;
            font-size: 1rem;
            margin-bottom: 0.25rem;
        }

        &__description {
            display: block;
            line-height: 1.5;
            color: #333;
        }
    }
    
    &__validation {
        button {
            font-size: 1.1rem;
            border: 0;
            background: #006cb4;
            color: #fff;
            padding: 10px 15px;
            border-radius: 5px;
        }
    }
}

.flex-margin-auto {
    display: flex;
    margin: auto;
    flex-direction: row-reverse;
}

.alert {
    position: absolute;
    left: auto;
    right: auto;
    width: 400px;
    margin-top: 25px;
    padding: 20px;
    border: 1px solid #ccc;
    border-radius: 5px;
    font-weight: 700;
    display: none;
}

.appear {
    display: block;
}

.success {
    border-color: green;
    color: green;
    background: #f2fff3;
}

.error {
    border-color: red;
    color: red;
    background: #fff9f9;
}

JavaScript

const cellphoneInput = document.getElementById('cellphone-input');
const checkButton = document.getElementById('check-button');
const cellphonePattern = new RegExp('^09[0-9]{8}');
const alert = document.getElementById('alert');

checkButton.addEventListener('click', () => {
    const result = cellphonePattern.test(cellphoneInput.value);

    if (!result) {
        alert.setAttribute('role', 'alert');
        alert.textContent = '不對喔,請依照電話格式輸入十個數字唷!'
        alert.classList.add('error');
        alert.classList.remove('success');
    } else {
        alert.textContent = '正確~~~';
        alert.classList.add('success');
        alert.classList.remove('error');
    }
    
    alert.classList.add('appear');
    cleanAlert();
})

function cleanAlert() {
    setTimeout(() => {
        alert.classList.remove('appear');
    }, 3000)
}

可以打開 Codepen 看動起來的樣子,用鍵盤操作看看。

這篇文章有示範了更多建立無障礙提示訊息的方法。


Reference


上一篇
實作無障礙網頁功能:鍵盤也能操作的手風琴 Accordion
下一篇
實作無障礙網頁功能:麵包屑 Breadcrumb
系列文
實踐無障礙網頁設計(Web Accessibility)30

1 則留言

0
史坦利
iT邦新手 5 級 ‧ 2020-07-22 12:03:30

想請問透過JS加role="alert"的目的為何?應該是不是也可以直接寫在HTML Tag上就好?

我要留言

立即登入留言