やりたかったこと:見た目を変えずに、キーボードと読み上げで使えるようにする
英語学習アプリ Words Admin(https://words-admin.web.app/)の画面の下の段には、AI-Phrase・AI-Memo・More などのタブが並んでいます。このタブは、キーボードだけで操作したときや画面の読み上げを使ったときに、ほとんど使えない状態でした。
作業の前に、次の4つを条件として決めました。
- 見た目は変えない
- 失敗を確かめるテスト(負のテスト)を付ける
- ローカルで確かめてから本番で確かめる
- 主要な導線の定期検査 25/25 を保つ
「見た目は変えない」は、言うだけで済ませずに、測って確かめる対象にしました。
何が壊れていたか
下の段は、見た目はタブでした。しかし中身は「クリックしたときの処理」だけを持つ <div> で、次の3つの問題がありました。
- 役割(role)も名前も無い。 キーボードの Tab で一度も止まらない。画面の読み上げでは「何か」としか分からない。
- 中にある飾りのアイコンボタンだけが焦点を受け取る。 押しても何も起きない行き止まりになっていた。
- 今どのタブにいるかが色だけで示されている。 意味としては出ていなかった。
見つけたきっかけは別の試験です。役割で探す書き方では、タブが見つかりませんでした。最初は試験の道具の誤りとして片付けかけました。しかし「役割も名前も無い」ことは、そのまま「キーボードと読み上げでは操作できない」ことを意味していました。道具の誤りではなく、本物の問題だったわけです。
どう直したか
直した内容は次の表のとおりです。
| 対象 | 直し方 |
|---|---|
| 各タブ | role="button"/tabIndex=0/aria-label/今いるタブに aria-current="page"/Enter と Space で移動 |
| Space | 既定の動作を止める(止めないと、押したのに画面だけ下に送られる) |
| More(メニューを開くタブ) | aria-haspopup="dialog"/開いているかを aria-expanded で示す |
| 飾りのアイコン | tabIndex={-1} と aria-hidden(焦点と読み上げから外す) |
| 入れ物 | <nav aria-label>(画面の中の「ナビゲーション」として読み上げで飛べる) |
| 焦点の輪 | :focus-visible のときだけ=マウスで押しても輪は出ない |
表のとおり、Space は既定の動作を止めないと、押したのに画面だけが下に送られます。飾りのアイコンは tabIndex={-1} と aria-hidden を付けて、焦点と読み上げの両方から外しました。前は焦点を受け取るのがこのアイコンだけで、押しても何も起きない行き止まりだったためです。
焦点の輪は :focus-visible のときだけ出します。マウスで押しても輪は出ません。
「見た目は変えない」を画素で測った
直す前の本番と直した後のローカルで、下の段の 64px を幅 390px で撮り、画素ごとに比べました。
結果は 異なる画素 0 / 24,960 です。
「見た目は変えない」を言うだけで終わらせないために撮りました。
テストは「直しを外したら落ちるか」まで確かめた
負のテストは12件で、そのうち5件が失敗を確かめるものです。
- 名前の無い焦点が下の段に残っていない(飾りが焦点を取り返すと落ちる)
- 飾りのアイコンは焦点を受け取らず、読み上げにも出ない
- Enter と Space 以外のキーでは移動しない
- Space の既定の動作(画面送り)を止めている
- Enter を押しても、押していないタブへは移動しない
テストが効いているかを見るため、直しを外して実測しました。結果は12件中 11件が落ちる でした。
通ったまま残った1件は「Enter と Space 以外では移動しない」です。壊れた状態では何も動かないので、このテストは通ります。これは「反応しすぎ」を見張るテストなので、それで正しい結果です。
作る途中で直したこともあります。最初の版では、直しを外すと全部が同じ1つの理由(入れ物が無い)で落ちていました。これでは何が壊れたのか分かりません。そこで、検査ごとに別々の理由で落ちるように作り直しました。
通しの試験にキーボードだけの段を足した
画面を通しで確かめる試験に、キーボードだけの段を足しました。マウスを使わず、Tab だけで下の段の AI-Memo に焦点を運びます。そこで Enter を押して一覧を開き、登録が1件以上あることを確かめます。
実測では Tab 8回で到達・役割は button・登録数 5 でした。
実測
| 結果 | |
|---|---|
| ローカル | 16/16・詰まり 0 |
| 本番 | 16/16・詰まり 0 |
| 主要な導線の定期検査 | 25/25 |
| 単体テスト | 148 passed(このタブの12件を含む) |
| 下の段の見た目 | 異なる画素 0 / 24,960 |
最初に決めた順番どおり、ローカルで確かめてから本番で確かめました。主要な導線の定期検査は 25/25 を保っています。
業務に置き換えると(社内ツール・業務画面のアクセシビリティ対応)
今回は英語学習アプリでの記録ですが、社内ツールや業務画面のアクセシビリティ対応にも同じ考え方が使えます。
- 「見た目を変えない」は、画素の比較で確かめられる。 変える前と変えた後を同じ幅で撮って比べれば、数字で残せます。
- テストは「直しを外したら落ちるか」まで確かめる。 外しても通るテストは何も守っていません。ただし「反応しすぎ」を見張るテストのように、壊れた状態で通るのが正しいものもあります。
- テストは、検査ごとに別々の理由で落ちるように作る。 全部が同じ1つの理由で落ちると、何が壊れたのか分かりません。
- 対応の範囲を、役割・名前・焦点・キー操作・現在地の5つに分けて点検すると漏れにくい。
- 役割で探して見つからないときは、道具の誤りと決めつけない。 今回は、それが「キーボードと読み上げでは操作できない」という本物の問題でした。
この記事は、TechAthletes が自社のサービスを作る中で記録した実測をもとに書いています。業務への導入のご相談は 仕事の窓口 で受け付けています。