失敗例で学ぶアクセシビリティ(WCAG 2.1)
2022/09/25はじめに
突然アクセシビリティ筋を鍛えたくなったのが先月の話です.
WCAG 2.1の日本語訳を全部読めばムキムキになれるのではと思い,先頭から読み進めて1ヶ月かかり読了しました.
中でも面白かったのは「失敗例」という項目です.ここには良くないWebページの実装例がたくさん書かれており,「あ〜初心者ならやりがちだよね〜」という例から「え…?職場のコードでやらかしてるんだが……?」みたいな例まであり,マジで死にたくなりました.
私の学習メモとして,またはアクセシビリティの入門資料として,あるいは過去の過ちへの禊として,やらかしそうな失敗例を, WCAG 2.1のすべての達成基準に対して 思いつく限りまとめようと思います.
レベル(A,AA,AAA)の低い順に記載しますので,下に行くほど発展的な内容になります.
失敗に気づいたら
「WCAG2.1 達成基準の番号 十分な達成方法」でググり,達成方法に関する公式の説明を見つけます.
例えば基準1.1.1なら以下の部分です.
十分な達成方法 - 達成基準 1.1.1: 非テキストコンテンツを理解する
予防線
この記事では簡単さを優先しています.用語や説明を言い換えたり,まとめたり,割愛したりしています.
入門資料には使えますが,厳格な適合評価などには使えません.
凡例
ここに成功例が書かれます
ここに失敗例が書かれます
レベルA
クリアすることで最低限のアクセシビリティが実現されるレベル
1. 知覚可能(A)
ユーザーがコンテンツを知覚(見る,聞く,触る…)できること
1.1 テキストによる代替(A)
テキストによる代替があること
1.1.1 非テキストコンテンツ
非テキストコンテンツ(写真,イラスト,グラフ,アスキーアートなど)に,適切な代替がある
代替がない
<p>以下は売上を表したグラフである</p>
<img src="graph.jpg" />
→目の見えない人には伝わらない
代替が不適切
<p>以下は売上を表したグラフである</p>
<img src="graph.jpg" alt="売上の推移.オレンジ色は今年度の売上を表す" />
ここでgraph.jpg
は以下の画像
→やはり伝わらない.売上は増加?減少?オレンジ色ってどこ?
装飾画像に代替がある
<!-- info_icon.gifは「i」を丸で囲ったようなアイコン -->
<a><img src="info_icon.gif" alt="インフォアイコン" />ヘルプ</a>
→「インフォアイコン」って読み上げられても…
<!-- spacer.pngは余白を調整するためだけの透明な画像 -->
<img src="spacer.png" alt="スペーサー" />
→「スペーサー」って読み上げられても…
装飾画像にalt属性がない
<img src="spacer.png" />
→支援技術が画像に反応してしまう
例えばスクリーンリーダーが「ラベルのない画像」と読み上げる
正しくはalt=""
CSSで重要な画像を表示している
<p>以下は歴史的に有名な写真です</p>
<span></span>
<style>
span {
background-image: url(image.jpg);
}
</style>
テキストだけどテキストじゃないものに代替がない
<p>ネ申</p>
<pre>
____ ∧ ∧
|\ /(´~`)\
| | ̄ ̄ ̄ ̄ ̄|
| |=みかん=|
\|_____|
</pre>
1.2 時間依存メディア(A)
ここでは以下の3つの基準をまとめて扱う.
- 1.2.1 音声のみ及び映像のみ(収録済)
- 1.2.2 キャプション(収録済)
- 1.2.3 音声解説、又はメディアに対する代替(収録済)
これらの基準では,収録済みの音声や映像について次のような代替を求める
音声ファイル(mp3など)に対する代替(書き起こしなど)がある
動画の音声トラックに対するキャプションがある
動画の映像トラックに対する音声解説または代替(書き起こしなど)がある
動画の音声トラックに対するキャプションがない
<video src="gag.mp4">一発ギャグ大会の動画記録</video>
<!-- この動画にはキャプションや書き起こしがない -->
→耳の聞こえない人には伝わらない
音声のキャプションや代替が不十分
<video src="gag.mp4">一発ギャグ大会の動画記録</video>
<!-- この動画には埋め込みのキャプション(オープンキャプション)がある -->
<!-- キャプション:サバンナ八木「ブラジルの人聞こえますかー!!!」 -->
→会場の反応(「笑い声が起こった」など)も書くべきである
このキャプションでは,ギャグがウケたのか滑ったのかわからない.したがって,音声を代替しきれていない
映像に対する音声解説や代替がない
<video src="gag.mp4">一発ギャグ大会の動画記録</video>
<!-- この動画には音声解説がない -->
→目の見えない人には伝わらない
映像の音声解説や代替が不十分
<video src="gag.mp4">一発ギャグ大会の動画記録</video>
<!-- この動画には音声解説が付属している -->
<!-- 音声解説:次の発表者であるサバンナ八木氏がステージに登場し,叫んだ -->
<!-- 動画音声:ブラジルの人聞こえますかー!!! -->
→地面に向かって叫んだことを説明していない
そのため,映像を代替しきれていない
1.3 適応可能(A)
様々な閲覧方法にコンテンツが適応できること.例えばスクリーンリーダーが読み上げる場合,CSSを無効化した場合など
1.3.1 情報及び関係性
情報,構造,関係性はプログラムによる解釈が可能
見た目,装飾のために間違った要素を使う
<p>新商品を開発しました</p>
<h2>好評発売中!</h2>
→文字を大きくするために見出しを使っている
<blockquote>定理:三角形の内角の和は180度になる</blockquote>
→字下げと強調のために引用を使っている
<fieldset>
<legend>今日の天気</legend>
<p>雷雨です</p>
</fieldset>
→枠線のためにfieldset
を使っている
カレーの作り方を説明します.<br />
<br />
まずスーパーに行きます.<br />
→改行のみで段落を表している
カレーの作り方を説明します.
<p></p>
まずスーパーに行きます.
→段落をスペーサーとして使っている
CSSで非装飾のコンテンツを提供している
<p>Vimは<span class="strong">最高のエディタです!</span></p>
<style>
.strong {
font-weight: bold;
}
</style>
→CSSを無効にしたとき意味が伝わらなくなる
<style>
.good:before {
content: "良いこと:";
}
.bad:before {
content: "悪いこと:";
}
</style>
<p class="good">ごはんをカレーと食べる</p>
<p class="bad">ごはんをシチューと食べる</p>
→CSSを無効にしたとき意味が伝わらなくなる
つまり,CSSを装飾以外に使っているため失敗
リンクをエミュレートしている
<img
src="download_button.png"
alt="ダウンロードページへ"
onclick="location.href='download.html'"
/>
→普通にa
タグを使おう
1.3.2 意味のある順序
コンテンツが正しい順序で解釈される
CSSでコンテンツの順序を変えている
例:以下はカレーのランディングページである
これは次のようなHTMLで書かれている
<div class="container">
<span>食べられる</span>
<span class="top-left">カレーを</span>
<span class="bottom-right">幸せ</span>
</div>
<style>
/* 省略 */
</style>
すべてのコード
<div class="container">
<span>食べられる</span>
<span class="top-left">カレーを</span>
<span class="bottom-right">幸せ</span>
</div>
<style>
.container {
position: relative;
width: 300px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.top-left {
position: absolute;
top: 0;
left: 0;
}
.bottom-right {
position: absolute;
bottom: 0;
right: 0;
}
</style>
→CSSを無効化すると「食べられるカレーを幸せ」となり,意味がわからなくなる
テーブルレイアウトを使用している
例:以下は俳句の表示例である
これは次のようなHTMLで書かれている.
<table>
<tr>
<td>水の音</td>
<td>蛙飛びこむ</td>
<td>古池や</td>
</tr>
</table>
<style>
td {
width: 1em;
}
</style>
→CSSを無効化すると「水の音蛙飛びこむ古池や」となってしまう
文字間隔の調整にスペースを使用している
<p>日本の地名</p>
<!-- 横幅を名古屋に合わせるため全角スペースを使用している -->
<ul>
<li>東 京</li>
<li>大 阪</li>
<li>名古屋</li>
</ul>
→スペースによって「とうきょう」が「ひがし,きょう」などと読まれてしまう
1.3.3 感覚的な特徴
コンテンツの説明が,構成要素の感覚的特徴(形,色,大きさ,位置,音など)だけに依存しない
コンテンツの説明が,構成要素の感覚的特徴だけに依存している
<p>赤いラベルは必須項目を表します</p>
<label for="name" style="color: red">氏名</label>
<input name="name" id="name" />
→目の見えない人には伝わらない
赤ってどこ?
<p>ダウンロードは画面右下のリンクから!</p>
→目の見えない人には伝わらない
右下にどのリンクが表示されてるの?
<!-- 簡単なクイズのページ -->
<!-- playは効果音を鳴らす独自のJavaScript関数 -->
<p>クイズ:どちらが美味しいお菓子でしょうか?</p>
<button onclick="play('正解音.mp3')">たけのこの里</button>
<button onclick="play('不正解音.mp3')">きのこの山</button>
→耳の聞こえない人にはどちらが正解かわからない
1.4 判別可能(A)
コンテンツを見やすく,聞きやすいものにすること.
1.4.1 色の使用
色が情報を伝えるための唯一の手段になっていない
また,本基準では以下も認めている.
色がリンクやコントロールを特定する唯一の手段だが,周囲のテキストと3:1以上のコントラスト比があり,フォーカス時に追加の視覚的手がかりがある
しかし,基本的には色以外にも情報伝達の手段を用意するのがベストプラクティスと思われる.
色が情報を伝えるための唯一の手段になっている
<img src="image.png" alt="姉妹の写真.うすい赤髪が姉,うすい青髪が妹" />
→髪の色を見分けられない利用者がいるかもしれない
特に年配,ロービジョン,色覚異常の利用者
リンクが他と見分けづらい
詳細は<a href="help.html">ヘルプ</a>を参照してください
<style>
body {
color: #000;
}
a {
text-decoration: none;
color: #575757;
}
</style>
これは次のように表示される
→リンクを見分けられない利用者がいるかもしれない
この場合のコントラスト比は2.9:1である.これは,達成基準の3:1を下回っているため失敗となる
1.4.2 音声の制御
自動再生され3秒以上長く続く音声を一時停止・停止・音量調整できる機構がある
音声が邪魔
<p>このページでは爆音ノリノリBGMが無限ループ再生されます!ノッていこうぜ!</p>
<audio src="bgm.mp3" autoplay loop></audio>
<!-- 注:コントロールはない -->
→スクリーンリーダーの読み上げが聞こえねぇよタコ
最近は自動再生しないブラウザも多い
2. 操作可能(A)
UIコンポーネント(ボタンやテキストボックスなど)とナビゲーションは操作可能でなければならない
2.1 キーボード操作可能(A)
キーボードで操作できること
2.1.1 キーボード
コンテンツのすべての機能はキーボードで操作できる
ただし,その機能が軌跡に依存している場合はのぞく
軌跡に依存する機能の例:ある保険の契約サイトでは,手書きのサインを画面に書く
署名は,その軌跡自体に意味があるため例外となる.一方で,単なる手書き文字入力機能の場合は例外にならない.その場合は追加のテキストボックスを設置すれば良い.
不完全なエミュレートを行っている
例:以下では,img
要素でボタンをエミュレートしている.マウスでは使用できる
<img onclick="alert('hello')" src="hello_button.png" alt="say hello" />
→しかしキーボードで操作できない
キーボードで操作するためには,フォーカス可能にする必要がある
フォーカスを強制的に解除している
<!-- ボタンに謎の枠線が表示されないように,this.blurを使ってみた -->
<button type="button" onclick="alert('hello')" onfocus="this.blur()">
say hello
</button>
→ボタンにフォーカスできないためキーボードで操作不能
UIコンポーネントにdisplay: none;
を使用している
<!-- カスタムのボタン -->
<label>
<!-- 実際のボタンはdisplay: noneで隠してしまって… -->
<input type="button" style="display: none" onclick="alert('hello')" />
<!-- こちらの要素を表示する.spanなのでスタイルを当てやすいぞ! -->
<span>say hello</span>
</label>
→実際のボタンをdisplay: none;
しているのでキーボードで操作できない.支援技術も反応しない.
UIコンポーネントを独自に実装しようとした場合の失敗例は4.1.2 名前(name)・役割(role)及び値(value)も参照
2.1.2 キーボードトラップなし
UIコンポーネントがフォーカスを受け取ったあと,キーボードだけでフォーカスを外せる
フォーカスを離さないUIコンポーネント
例:このテキストボックスはなにか値を入力するまでフォーカスを離さない
<label>
名前(必須)
<input />
</label>
<script>
const input = document.querySelector("input");
input.addEventListener("keydown", (e) => {
if (e.key === "Tab" && input.value === "") {
input.focus();
e.preventDefault();
}
});
</script>
→そのことを知らないキーボード利用者はここから抜け出せなくなり,困惑する.
フォーカスを捕まえるFlash,アプレットコンテンツ
→最近はあまりない
2.1.4 文字キーのショートカット
単純な(文字,句読点,記号のみの)キーボードショートカットが無い
単純なショートカットがある場合:ショートカットを解除できる,または再割当てできる,またはフォーカス時のみ限定的に有効である
単純なショートカット
例:あるメール管理画面では,次のショートカットが利用可能である
- d: メールを削除する(delete)
- y: ダイアログにイエスで答える(yes)
シナリオ:アリスは障害のため音声入力を利用している.メール管理画面の閲覧中に,同僚のデイジーがやってきた.アリスは「ハイ,デイジー」と言った.
ここで音声入力が作動し「Hi, D ais y 」と入力された.これにより
- 「D」によってメールの削除が反応した
- 「本当に削除しますか?」のダイアログが出たが「y」によって削除が実行されてしまった
2.2 十分な時間(A)
コンテンツを読み,使用する十分な時間があること
2.2.1 タイミング調整可能
コンテンツに制限時間がない
制限時間がある場合,次のいずれかである
- 制限時間を解除できる
- 時間を10倍に変更できる
- 少なくとも20秒の猶予をもって時間を10倍以上に延長できる
- リアルタイムのイベント(例:オークション)
- 制限時間が必要不可欠
- 制限時間が20時間より長い
コンテンツに短い時間制限がある
例:あるサイトは移転済みのページに対して以下のようなコンテンツを返す
<head>
<title>これは古いページです</title>
<meta http-equiv="refresh" content="5; url=http://www.example.com/newpage" />
</head>
<body>
<p>
このページは古く,新しいドメインに移転しました..5秒後にリダイレクトします.
</p>
</body>
→スクリーンリーダー「これは古いページです.このページは古く,新しいドメインに(リダイレクトにより読み上げ中断)」
→ユーザー「???(困惑)」
一定時間でページを再読込している
<!-- ある古のチャットサイトは,一定時間で自分自身を再読込する -->
<head>
<title>チャット</title>
<meta http-equiv="refresh" content="5; url=http://www.example.com/chat" />
</head>
<body>
<h1>メッセージ一覧</h1>
…
</body>
→スクリーンリーダー「チャット,メッセージ一覧.チャット,メッセージ一覧.チャット,メッセージ一覧……」
2.2.2 一時停止、停止、非表示
自動で動く,または点滅するコンテンツがない
自動で動く,または点滅するが,次のいずれかである
- 5秒以内に止まる
- 停止する,または非表示にする機能がある
- 単独で提示される
- 必要不可欠
動く必要のないコンテンツが動いている
<!-- 目立たせるために点滅させる -->
<blink>セール実施中!</blink>
<h2>過去の商品</h2>
…
<!-- 証券取引所にならって,横スクロールで株価を表示する -->
<marquee>最新の株価情報:今日の株価は…</marquee>
<h2>その他の情報</h2>
…
→とめるべき
注意欠陥障害をもつユーザーは,動くコンテンツを追うのがストレス.また,それらに気を取られると,動いていないコンテンツも読みづらくなる
2.3 発作と身体的反応(A)
発作を起こすようなコンテンツは作成しないこと
2.3.1 3 回の閃光、又は閾値以下
どの1秒間にも3回の閃光を放つものがない
1秒間に3回の閃光を放つが,その面積が21,824平方ピクセルよりも小さい(一般的な画面サイズと距離の場合)
基準を上回る閃光がある
例:ある広告はユーザーの注意を引くために,大きな面積で素早く点滅する
→点滅をやめるべき
光過敏性発作に関するガイドラインは,Webだけでなくゲーム業界,テレビ業界でも規定されている
2.4 ナビゲーション可能(A)
利用者がサイト内で迷わないこと
2.4.1 ブロックスキップ
ヘッダーブロックをスキップする方法がある
ヘッダーブロックをスキップできない
<body>
<ul>
<li><a>ナビゲーションリンク1</a></li>
<li><a>ナビゲーションリンク2</a></li>
<li><a>ナビゲーションリンク3</a></li>
…
</ul>
<div>広告1</div>
<div>広告2</div>
<div>広告3</div>
…
<span>重要情報:明日メンテナンスを行います</span>
<p>それでは本題ですが…</p>
</body>
→本文まで長い
目のみえる人は,ヘッダーや広告を無視してページの全体像を把握できる.しかし,そうでない人にとっては難しい
例えば,本文直前にh1
見出しを置く,本文をmain
要素でかこむ,ヘッダーブロックのスキップリンクを設置すると良い
2.4.2 ページタイトル
わかりやすいページタイトルがついている
ページタイトルがデフォルトのまま
<head>
<title>無題のドキュメント</title>
</head>
→なんのページ?
ページのタイトルが不明瞭
例:スミスさんはABC銀行のオンラインバンキングを利用している
<head>
<title>口座情報</title>
</head>
→どの銀行かわからない.スミスさんは他の銀行にも口座をもっている
<head>
<title>口座情報 | ABC銀行</title>
</head>
→どの口座かわからない.スミスさんはABC銀行に複数の口座をもっている
<head>
<title>口座番号 123-4567 の情報 | ABC銀行</title>
</head>
→「情報」は少し曖昧かもしれない.もしさらにタイトルを限定できるなら,「残高」や「直近の取引」のほうが良いかもしれない
2.4.3 フォーカス順序
フォーカス順序が意味および操作性を損なわない
DOMの順序が見た目と一致していない
例:以下は市のページ.上部に重要な情報が書かれている
これは次のようなHTMLで書かれている
<h1>市のページ</h1>
<h2>ゴミの出し方</h2>
…
<h2>市長の日記</h2>
…
<h2>よくある質問</h2>
…
<strong class="emergency">
緊急情報!!!地球が爆発します!
<a href="http://example.com/emergency">詳細はこちら</a>
</strong>
<style>
body {
padding: 50px 10px;
}
.emergency {
position: absolute;
top: 0;
left: 0;
padding: 0.5em;
color: yellow;
background: black;
}
.emergency a {
color: red;
}
</style>
→目が見えてキーボードを使っている利用者は困惑する.ページ上部にあるのに,フォーカスを移動させるには「ゴミの出し方」「市長の日記」「よくある質問」などを通過しなければならない
→目の見えない利用者は,重要な情報を最後に見つけることになる.
モーダルダイアログにフォーカスが移動しない,フォーカストラップがない
例:以下のようなモーダルダイアログの実装がある
<button onclick="document.querySelector('.dialog').style.visibility='visible'">
ダイアログを開く
</button>
<div class="dialog">
<div>
<p>これはモーダルダイアログです</p>
<button
onclick="document.querySelector('.dialog').style.visibility='hidden'"
>
閉じる
</button>
</div>
</div>
<button>他のボタン</button>
<style>
/* 省略*/
</style>
すべてのコード
<button onclick="document.querySelector('.dialog').style.visibility='visible'">
ダイアログを開く
</button>
<div class="dialog">
<div>
<p>これはモーダルダイアログです</p>
<button
onclick="document.querySelector('.dialog').style.visibility='hidden'"
>
閉じる
</button>
</div>
</div>
<button>他のボタン</button>
<style>
.dialog {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: #0009;
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
}
.dialog div {
padding: 1em;
background: white;
}
</style>
ここで,以下の操作をしたとする
- Tabキーで「ダイアログを開く」にフォーカスを当て,Space キーでボタンを押した
- しかし,フォーカスは「ダイアログを開く」のままである.
- ダイアログの暗い背景でフォーカスインジケーターが見えず,利用者は自身の位置を見失ってしまった
→モーダルダイアログを開いたときに,ダイアログ内にフォーカスが移るべきだった
続けて,以下の操作をしたとする
- 利用者は,なんとか苦労して「閉じる」ボタンにフォーカスを当てた
- しかし,誤ってもう一度Tabキーを押してしまった.
- フォーカスは「他のボタン」に移ってしまい,また自身の位置を見失った
→モーダルダイアログにフォーカストラップがあるべきだった
モードレスダイアログがDOM的に遠くにある
例:以下のようなモードレスダイアログの実装がある
<button onclick="document.querySelector('.dialog').style.visibility='visible'">
ダイアログを開く
</button>
<button>他のボタン1</button>
<button>他のボタン2</button>
<button>他のボタン3</button>
<div class="dialog">
<div>
<p>これはモードレスダイアログです</p>
<button
onclick="document.querySelector('.dialog').style.visibility='hidden'"
>
閉じる
</button>
</div>
</div>
<style>
/* 省略 */
</style>
すべてのコード
<button onclick="document.querySelector('.dialog').style.visibility='visible'">
ダイアログを開く
</button>
<button>他のボタン1</button>
<button>他のボタン2</button>
<button>他のボタン3</button>
<div class="dialog">
<div>
<p>これはモードレスダイアログです</p>
<button
onclick="document.querySelector('.dialog').style.visibility='hidden'"
>
閉じる
</button>
</div>
</div>
<style>
.dialog {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
}
.dialog div {
padding: 1em;
border: 3px solid black;
}
</style>
ここで,以下の操作をしたとする
- Tabキーで「ダイアログを開く」にフォーカスを当て,Space キーでボタンを押した
- ダイアログが開いた.利用者はダイアログを消したいと考えた
- 「閉じる」ボタンを操作するためにTabキーを押したが,フォーカスは「他のボタン1」に移った
- 同様に「他のボタン2」「他のボタン3」を経由して,やっと「閉じる」ボタンにたどり着いた
→モードレスダイアログは,トリガーの近くに配置すべきである
最近では,自身でダイアログを実装するのではなく,dialog
要素の使用を検討してもいいかもしれない.dialogの仕様ではフォーカス管理も考慮されている.
2.4.4 リンクの目的(コンテキスト内)
リンクのテキスト単独で,その目的が判断できる
リンクのテキストとコンテキストから,その目的が判断できる
リンクテキストとコンテキストから目的がわからない
<h1>日記一覧</h1>
<p>2022/09/24:今日はプログラミングの勉強をしました.具体的には…</p>
<p><a>続きを読む</a></p>
→日記のプレビューとリンクを同じ段落にすべき
利用者は「続きを読む」が何の続きを読むリンクなのかわからない
2.5 入力モダリティ(A)
様々な入力機器で操作しやすいこと
2.5.1 ポインタのジェスチャ
マルチポイントで操作する機能は,シングルポインタでも操作できる
軌跡ベースのジェスチャで操作する機能は,シングルポインタでも操作できる
マルチポイントでしか操作できない機能がある
例:ある地図アプリでは,ピンチイン / アウトでしか地図を拡大 / 縮小できない.
→以下のような人には利用できない
- マルチポイント環境だが障害によりジェスチャを遂行できない
- マルチポイント環境ではない
- マウス
- ヘッドポインタ
- 視線システム
- 音声制御マウスエミュレーター
拡大・縮小ボタンを配置すべき
軌跡ベースのジェスチャでしか操作できない機能がある
例:Web上で動く迷路ゲームは,ドラッグ操作でのみ自機を操作できる
→ジェスチャを遂行できない人には利用できない
例えば自機を操作できる「上」「下」「左」「右」のボタンを配置する
2.5.2 ポインタのキャンセル
シングルポインタでの操作は,キャンセル可能である
ダウンイベントで機能を実行している
<button onmousedown="alert('削除しました')">アカウントを削除します</button>
→意図せずボタンを押し込んでしまった場合,アカウントが削除されてしまう
onclick
を使用していれば,ボタンを押し込んだままポインタを外すことでキャンセルできた
2.5.3 名前(name)のラベル
UIコンポーネントのラベルが名前(アクセシブルな名前)に含まれる
UIコンポーネントのラベルが名前に含まれていない
発送先:<input />
→input
には何の名前もついていない
発送先:<input name="発送先" />
→やはりinput
には何の名前もついていない
アクセシブルな名前とname
属性を混同している
<label>発送先:</label><input />
→やはりinput
には何の名前もついていない
label
要素を使用しているがinput
と関連がない
発送先:<input title="所在地" />
→ラベルと名前がずれている.以下のようなシナリオが考えられる
- スクリーンリーダー「発送先」
- 目の見えないユーザー「発送先を入力するるんだな.(Tabキーを押下)」
- スクリーンリーダー「テキストボックス,所在地」
- ユーザー「あれ?発送先じゃなかったの?発送先と所在地って一緒の意味なのか……?」
または
- 音声入力ユーザー「(画面を見て)お,発送先を入力するんだな.『発送先テキストボックスに,フォーカス』」
- 支援技術「『発送先テキストボックス』は見つかりません」
- ユーザー「???」
2.5.4 動きによる起動
デバイスや利用者の動きで操作できる機能は,UIコンポーネントでも操作できる
デバイスや利用者の動きで操作できる機能は,動きへの反応を無効化できる
動きでのみ操作できる機能がある
例:あるスマートフォン向けシューティングゲームサイトは,端末を傾けることで自機を操作する.それ以外に操作方法はない
例:あるスマートフォン向けSNSサイトは,同時に2つの端末を振ることでアカウントを相互フォローできる.それ以外にフォローの方法はない
→以下の利用者がサイトを使えない
- 端末にセンサーが搭載されていない
- 運動障害があり,動きを遂行できない
- 端末が机やベッドに固定されている
同等の機能を提供するボタンなどを設置するべき
動きに対する反応を無効化できない
例:あるスマートフォン向け地図サイトは,地磁気センサによって地図が自動回転する.しかしそれを止められない
→センサに問題がある場合,またはスマートフォンを立てて持った場合などに地図が見づらい
3. 理解可能(A)
理解しやすいコンテンツを作ること
3.1 読みやすさ(A)
読みやすいコンテンツを作ること
3.1.1 ページの言語
ウェブページの自然言語がどの言語か解釈可能である
ウェブページの自然言語がどの言語か解釈可能でない
<!DOCTYPE html>
<html>
<head>
<title>お好み焼きはご飯のおかずとなるか</title>
</head>
<body>
<p>ならない</p>
</body>
</html>
→言語の指定がない
<!DOCTYPE html>
<html lang="en">
<head>
<title>コロッケはご飯のおかずとなるか</title>
</head>
<body>
<p>なる</p>
</body>
</html>
→言語の指定が間違っている
スクリーンリーダーは誤った音声エンジンで読み上げてしまうかもしれない
3.2 予測可能(A)
コンテンツの挙動が予測可能であること
3.2.1 フォーカス時
UIコンポーネントがフォーカスを受け取ったとき,コンテキストの変化を引き起こさない
UIコンポーネントがフォーカスを受け取ったとき,コンテキストの変化を引き起こす
例:あるフォームでは,ヘルプボタンがフォーカスを受け取ったときにダイアログを表示する
コードを見る
<div>
<label>氏名:<input /></label>
<button data-help="氏名とは,名前のことです">ヘルプ</button>
</div>
<div>
<label>住所:<input /></label>
<button data-help="住所とは,あなたが住んでいる場所のことです">ヘルプ</button>
</div>
<dialog>
<form method="dialog">
<p></p>
<button>閉じる</button>
</form>
</dialog>
<script>
// ヘルプボタンにフォーカスが移ったらメッセージを表示する
let last;
for (const button of document.querySelectorAll("button[data-help]")) {
button.addEventListener("focus", (e) => {
if (last === e.target) return;
last = e.target;
document.querySelector("dialog p").textContent = e.target.dataset.help;
document.querySelector("dialog").showModal();
});
}
</script>
→キーボードで操作すると,すべてのヘルプメッセージを見ることになり煩雑
例えば,クリックでメッセージを表示するようにする
3.2.2 入力時
UIコンポーネントの設定を変更しても,コンテキストが予期せず変化しない
UIコンポーネントの設定を変更すると,コンテキストが予期せず変化する
例:自動送信
<form action="#">
<!-- 省略 -->
</form>
<script>
// 選択肢を選んだときに自動送信
// 送信ボタンを押さなくていいからラクだよね
for (const input of document.querySelectorAll("input")) {
input.addEventListener("change", () =>
document.querySelector("form").submit()
);
}
</script>
すべてのコード
<form action="#">
<fieldset>
<legend>一番優れているエディタを選択してください</legend>
<div>
<input type="radio" name="editor" id="vim" value="vim" />
<label for="vim">Vim</label>
</div>
<div>
<input type="radio" name="editor" id="emacs" value="emacs" />
<label for="emacs">Emacs</label>
</div>
<div>
<input type="radio" name="editor" id="vscode" value="vscode" />
<label for="vscode">Visual Studio Code</label>
</div>
</fieldset>
</form>
<script>
// 選択肢を選んだときに自動送信
// 送信ボタンを押さなくていいからラクだよね
for (const input of document.querySelectorAll("input")) {
input.addEventListener("change", () =>
document.querySelector("form").submit()
);
}
</script>
→項目を選択しただけなのにフォームが送信されてしまう
間違った選択肢を選んでも訂正できない
3.3 入力支援(A)
間違いを防ぎ,修正を支援すること
3.3.1 エラーの特定
エラーが検出されたときは,その箇所が特定され,エラー内容がテキストで説明される
エラーが検出されたが,その内容の提示が不適切
例1:ある登録フォームを送信したが,次のようなページが返ってきたとする
<form action="#">
<label>名前:<input /></label>
<label>メールアドレス:<input /></label>
<p style="color: red">エラーがあります</p>
<button>送信</button>
</form>
→目の見えないユーザーは,そもそもエラーに気づかないかもしれない
「送信したのに同じページが返ってきたぞ」と思い,読み進めて初めてエラーがあったことに気づく
例2:例1を改良して,エラーに気づきやすくした
<head>
<title>エラーあり | 登録フォーム</title>
</head>
<body>
<form action="#">
<p style="color: red" tabindex="-1">エラーがあります</p>
<label>名前:<input /></label>
<label>メールアドレス:<input /></label>
<button>送信</button>
</form>
<script>
document.querySelector("p").focus();
</script>
</body>
→エラーに気づけるようにはなった
しかし,どの項目がどんなエラーなのかわからないため修正できない
3.3.2 ラベル又は説明
利用者の入力を要求する場合は,ラベルまたは説明文がある
ラベルまたは説明文がない
電話番号を入力:<input /> - <input /> - <input />
<style>
input {
width: 4em;
}
</style>
→各input
に説明文がない.
→各input
のラベルはそれぞれ「電話番号を入力:」「-」「-」だが,意味がわからない
見た目上は典型的な電話番号のフォーマットを要求しているが,目の見えない人には分かりづらい
4. 堅牢(A)
様々なUAが解釈できるように,堅牢なコンテンツを作成すること
4.1 互換性(A)
様々なUAとの互換性を最大化すること
4.1.1 構文解析
開始タグには対応する閉じタグがある
要素は使用に応じて入れ子になっている
IDには重複がない
マークアップが正しくない
<p>
<div></p>
</div>
<form>
<form></form>
</form>
<div id="div1"></div>
<div id="div1"></div>
4.1.2 名前(name)・役割(role)及び値(value)
すべてのUIコンポーネントの名前と役割は解釈可能
すべてのUIコンポーネントの状態とプロパティは解釈可能
この基準では,独自のUIコンポーネントを作成する場合を対象にしている.したがって,UA標準のUIコンポーネント(input
要素など)を利用する場合は,本基準は達成される
UIコンポーネントの実装が不完全
例:独自の見た目のチェックボックスを以下のように実装した.これはマウス,キーボードどちらでも操作可能である
<div tabindex="0">独自のチェックボックス</div>
<script>
const checkbox = document.querySelector("div");
const toggle = () => checkbox.classList.toggle("checked");
checkbox.addEventListener("click", toggle);
checkbox.addEventListener("keypress", (e) => {
switch (e.key) {
case " ":
case "Enter":
toggle();
}
});
</script>
<style>
div:before {
content: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><rect style="fill: none; stroke: black; stroke-width: 2" width="16" height="16" /></svg>');
}
div.checked:before {
content: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><rect style="fill: none; stroke: black; stroke-width: 2" width="16" height="16" /><path style="fill: none; stroke: black; stroke-width: 2" d="m 2.6,8 4,5.3 6.6,-10.5" /></svg>');
}
</style>
→役割が支援技術に伝わっていない.role="checkbox"
が必要
支援技術はチェックボックスがあることすらわからない
→状態が支援技術に伝わっていない.aria-checked
属性が必要
支援技術は,チェックボックスがチェックされているかどうか利用者に伝えられない
レベルAA
公共サイト1など,アクセシビリティが重要なサイトでは失敗したくないレベル
1. 知覚可能(AA)
ユーザーがコンテンツを知覚(見る,聞く,触る…)できること
1.2 時間依存メディア(AA)
時間に依存するメディアに代替コンテンツがあること
1.2.4 キャプション(ライブ)
ライブ動画配信にキャプションがある
ライブ動画配信にキャプションがない
例:一発ギャグ大会のライブ動画配信を行っているサイトがある.しかしキャプションが提供されていない
→キャプションを提供する.以下のような方法が考えられる
- ライブが台本通りに進んでいるなら,台本のテキストを提供
- 速記を用いた高速入力技術
- 高速タイピング技術(ステノキャプショナー)
- 音声認識技術(ライブ音声を入力する,またはライブ音声を人間が聞き取って復唱し入力する)
キャプションの例はレベルAの時間依存メディアの説明を参照
1.2.5 音声解説(収録済)
収録済みの映像に音声解説がある
この基準は,レベルAにおける「1.2.3: 音声解説、又はメディアに対する代替(収録済)」の強化版である.レベルAでは,映像に代替をつければ音声解説は必要なかったが,この基準では必要である.
映像に音声解説がない
音声解説の例はレベルAの時間依存メディアの説明を参照
1.3 適応可能(AA)
様々な閲覧方法にコンテンツが適応できること.例えば端末の向きを変えるなど
1.3.4 表示の向き
コンテンツがデバイスの向き(横向き,縦向き)を制限しない
特定の向きでしかコンテンツが見られない
コードを見る
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<style>
body {
margin: 0;
padding: 0;
}
@media all and (orientation: landscape) {
body {
position: absolute;
top: 0;
left: 0;
width: 100vh;
height: 100vw;
transform: rotate(90deg) translateY(-100vw);
transform-origin: top left;
}
}
</style>
</head>
<body>
<h2>縦向きのサイト</h2>
<p>このWebサイトはスマホの縦向きに最適なデザインです!</p>
</body>
</html>
→やめるべき
例えば,車椅子の腕にデバイスを横向き固定している利用者もいる.そのような場合このサイトはとても見づらい
他にも,特定の向きでコンテンツを非表示にする,画面が回転されたらアラートを表示するなどの失敗例が考えられる
1.3.5 入力目的の特定
適切なautocomplete
属性を使用している
autocomplete
属性が不適切
新しいパスワード:<input type="password" />
→どんなパスワード?autocomplete
属性がない.autocomplete="new-password"
が適切
誕生日:<input type="date" />
→どんな日付?autocomplete
属性がない.autocomplete="bday"
が適切
生まれた年(例:1996):<input type="text" autocomplete="bday" />年
→bday
は年月日全体.bday-year
が適切
誕生日:<input type="text" autocomplete="birthday" />
→不正なautocomplete
属性値.bday
が正しい
名前(姓):<input type="text" autocomplete="name" />
→name
は名前全体.family-name
が適切
表示される名前:<input type="text" autocomplete="username" />
→nickname
のほうが適切かもしれない.一方で,nickname
を削除すべきとの声もあるため注意
まとめると,autocomplete
属性を正しく設定することには以下の利点がある
- UAやパスワードマネージャの自動入力により手間を省ける
- 記憶しなくて良い:特に言語や記憶の障害を持つ場合に有用
- 入力しなくて良い:特に運動障害を持つ場合に有用
- UAが目的を解釈し,追加のヒント画像を提供できる:脳性麻痺,脳卒中,頭部損傷,運動ニューロン疾患および学習障害を持つ場合,コミュニケーションに画像を好む場合がある.このような場合にUAは,例えば
autocomplete="bday"
の項目前にケーキのアイコン,autocomplete="tel"
の項目前に電話のアイコンを表示できる
1.4 判別可能(AA)
コンテンツを見やすいものにすること.
1.4.3 コントラスト(最低限)
サイズの大きなテキストに,3:1以上のコントラストがある
そうでないテキストに,4.5:1以上のコントラストがある
ここで「サイズの大きなテキスト」とは,以下の条件に当てはまるもの
- 英文の場合:約24px以上の通常の文字,または約18.6px以上の太字
- 邦文の場合:約29px以上の通常の文字,または約24px以上の太字
十分なコントラスト比がない
コードを見る
<p>
<span class="normal">normal size text</span>
<span class="normal">normal size bold text</span>
<span class="normal">通常サイズの文字</span>
<span class="normal">通常サイズの太字</span>
<span class="big">big size text</span>
<span class="big">big size bold text</span>
<span class="big">サイズの大きな文字</span>
<span class="big">サイズの大きな太字</span>
</p>
<style>
.normal {
color: #26a269;
background: #292929;
}
.big {
color: #792b82;
background: #9a9996;
}
span:nth-of-type(1) {
font-size: 16px;
}
span:nth-of-type(2) {
font-size: 14px;
font-weight: bold;
}
span:nth-of-type(3) {
font-size: 20px;
}
span:nth-of-type(4) {
font-size: 16px;
font-weight: bold;
}
span:nth-of-type(5) {
font-size: 24px;
}
span:nth-of-type(6) {
font-size: 19px;
font-weight: bold;
}
span:nth-of-type(7) {
font-size: 29px;
}
span:nth-of-type(8) {
font-size: 24px;
font-weight: bold;
}
span {
padding: 1em;
}
p {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
</style>
→通常サイズのテキストのコントラスト比は4.47:1であり,基準を下回っている.
→サイズの大きなテキストのコントラスト比は2.97:1であり,基準を下回っている
前景色または背景色だけを指定している
<p style="color: red">文字色だけ指定</p>
<p style="background: red">背景色だけ指定</p>
→UAの設定によってはコントラスト比を保証できない
特定の前景色と背景色の組み合わせを好む利用者がいる.UAにそれらの組み合わせを設定していた場合,上記の例では前景色だけ,または背景色だけがUAの設定になってしまう.
1.4.4 テキストのサイズ変更
支援技術なしで200%までテキストサイズをズームできる
今日のモダンブラウザは標準的にズーム機能を備えている.そのため,一昔前にサイト上部で見かけたような,テキストサイズを変更するコントロールの必要性は低くなったと言える.
モダンブラウザのズーム機能を邪魔しないようにコンテンツを制作することが重要である
テキストサイズをズームするとコンテンツが利用できなくなる
<div>こんにちは.今日はとてもいい天気ですね.</div>
<style>
div {
width: 100%;
border: 3px solid black;
overflow: hidden;
word-break: keep-all;
}
</style>
これを通常のズームで表示すると以下のようになる
しかし200%のズームで表示すると以下のようになる
→はみ出した部分が表示されていないため,弱視の利用者などはコンテンツを読めない可能性がある
1.4.5 文字画像
文字画像ではなくテキストが用いられている
または,文字画像の色,フォント,サイズ,色,背景色をカスタマイズできる
ただし,必要不可欠なものは例外
必要不可欠な例:あるフォントの販売ページでは,製品の書体を画像で伝えている
文字画像が用いられている
<img src="cashback.jpg" alt="キャッシュバック" />
→テキストとCSSを用いて近いスタイルを実現すべき
ロービジョンおよび視線移動に問題のある利用者が,文字のフォント,サイズ,色,背景色,文字間,行間をカスタマイズできない
1.4.10 リフロー
縦スクロールのコンテンツは,機能を損なうことなくかつ,320pxの横幅で横スクロールせずに利用可能
横スクロールのコンテンツは,機能を損なうことなくかつ,256pxの縦幅で縦スクロールせずに利用可能
縦スクロールコンテンツで横スクロールが必要
<div>
山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。
</div>
<style>
div {
margin: auto;
width: 500px;
}
</style>
これを600pxの横幅で表示すると以下のようになる.全文が見えている
しかし320pxの横幅で表示すると以下のようになる.文章を読むには横スクロールが必要
→横スクロールが表示されないようにレイアウトを変える必要がある
狭い画面で機能を損なっている
<div>
<span>新商品のご案内</span>
<span>製品情報</span>
<span>この会社について</span>
<span>お問い合わせ</span>
<span class="search"><input /><button>検索</button></span>
</div>
<style>
div {
display: flex;
justify-content: space-between;
}
@media screen and (max-width: 750px) {
.search {
display: none;
}
}
</style>
これを800pxの画面幅で見ると,ヘッダー内に検索ボックスが表示されている
しかし600pxの画面幅で見ると検索ボックスが消えている
→画面が狭い場合も検索ボックスを表示できるレイアウトにすべき
1.4.11 非テキストのコントラスト
UIコンポーネント自体および状態を,3:1以上のコントラストで識別できる
コンテンツ理解に必要なグラフィック部分を,3:1以上のコントラストで識別できる
UIコンポーネントに十分なコントラスト比がない
例:以下のチェックボックスのスタイルには十分なコントラスト比がない
コードを見る
<div>チェックされていない</div>
<div class="checked">チェックされている</div>
<div class="focused">フォーカスされている</div>
<style>
div:before {
content: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><rect style="fill: none; stroke: %2397979B; stroke-width: 2" width="16" height="16" /></svg>');
}
div.checked:before {
content: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><rect style="fill: none; stroke: black; stroke-width: 2" width="16" height="16" /><path style="fill: none; stroke: %2329AE70; stroke-width: 2" d="m 2.6,8 4,5.3 6.6,-10.5" /></svg>');
}
div.focused:before {
content: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px"><rect style="fill: none; stroke: %235999E8; stroke-width: 5" width="16" height="16" /></svg>');
}
</style>
→チェックされていないボックスの枠線は#97979B
色であり,背景とは2.91:1のコントラスト比で十分でない
→チェックマークは#29AE70
色であり,背景とは2.84:1のコントラスト比で十分でない
→フォーカス時の枠線は#5999E8
色であり,背景とは2.93:1のコントラスト比で十分でない
グラフィック部分に十分なコントラスト比がない
例:以下では映画の評価を5段階の星で表している
→それぞれの塗り色(#FFE620
と#FFFFFF
)のコントラスト比は1.26:1であるため十分でない.
コンテキストの理解のためにいは,それぞれの星を識別する必要がある.2種類の星の違いは塗り色だけであるため,そのコントラスト比が要件に挙がる.
例:以下は円グラフである.それぞれの項目が3段階の青色で表現されている.
→コントラスト比が十分でない境界が複数ある
この円グラフでは,各項目の境界がコンテキストにとって重要である.そのため,塗り色のコントラスト比が要件に挙がる.
1番濃い青色(#007EFF
)と2番目(#00ACFF
)とのコントラスト比は1.53:1であり十分でない.また,2番目(#00ACFF
)と3番目(#00E0FF
)の青色のコントラスト比は1.57:1であり,これも十分でない.さらに,2番目,3番目の青色と背景色(#FFFFFF
)のコントラスト比も基準を下回っている.
例:以下はカレーライスのイラストである
→皿の色#DFDFDF
とライス部分および背景の色#ffffff
とのコントラスト比は1.33:1であり,十分ではない
カレーライスと説明されるイラストにとって,ライスを識別できることはコンテキストの理解に必須である.そのためライス境界部分のコントラスト比が要件に挙がる.
1.4.12 テキストの間隔
以下のスタイル変更を行ったときにコンテンツを利用できる
- 行の間隔を,フォントサイズの1.5倍に設定する
- 段落の間隔を,フォントサイズの2倍に設定する
- 文字の間隔を,フォントサイズの0.12倍に設定する
- 単語の間隔を,フォントサイズの0.16倍に設定する
テキストの間隔を変更したときにコンテンツを利用できない
例:以下はページトップにバナーのあるサイトである
コードを見る
<div>
<h1>支援のお願い</h1>
<p>
このサイトは皆様からの支援金で運営されております.現在運営資金が少なく大変苦しい状況です.お1人あたりコーヒー1杯分の寄付で結構です.ご検討お願いいたします.
</p>
<a href="#">支援はこちらから</a>
</div>
<h1>百科事典</h1>
<p>百科事典とは,あやゆる分野の固有名詞について説明を集めた書籍である.</p>
<style>
body {
padding-top: 200px;
line-height: 1;
}
div {
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 200px;
border: 3px solid blueviolet;
}
</style>
このサイトを行間1.5で表示すると以下のようになる
→バナーの文字が本文と重なってしまっている
1.4.13 ホバー又はフォーカスで表示されるコンテンツ
ホバーやフォーカスで追加のコンテンツが現れる場合は,以下を満たす
- ポインターやフォーカスを動かさずに表示を消せる
- 追加のコンテンツにもホバーできる
- ポインターやフォーカスを移動するまで表示が継続される
追加のコンテンツが上記条件を満たさない
例:以下はツールチップの実装例である.ヘルプという文字をホバーするとチップが表示される.チップは3秒経過すると非表示になる
コードを見る
<label>
郵便番号:
<input />
</label>
<span>ヘルプ</span>
<div>
郵便番号は以下のルールで入力してください
<ul>
<li>郵便マーク〒は入力しないでください</li>
<li>半角数字で入力してください</li>
<li>ハイフンは省いてください</li>
</ul>
郵便番号がわからない方:<a href="#">郵便番号検索</a>
</div>
<script>
const tooltip = document.querySelector("div");
const helpText = document.querySelector("span");
const timer = null;
helpText.addEventListener("mouseenter", () => {
tooltip.style.display = "block";
clearTimeout(timer);
setTimeout(() => {
tooltip.style.display = "none";
}, 3000);
});
helpText.addEventListener("mouseleave", () => {
tooltip.style.display = "none";
});
</script>
<style>
div {
display: none;
border: 3px solid blue;
}
</style>
→ポインターを移動させないとツールチップを非表示にできない
利用者は意図せずフォーカスしてしまったかもしれない.例えば,画面を特に拡大している場合はポインターを外しにくいかもしれない.
→追加コンテンツにホバーできない
したがって,「郵便番号検索」リンクはマウスでクリックできない
→表示が継続されない
3秒でツールチップが消えてしまうため,内容を最後まで読めない可能性がある
2. 操作可能(AA)
ナビゲーションは操作可能でなければならない
2.4 ナビゲーション可能(AA)
利用者がサイト内で迷わないこと
2.4.5 複数の手段
Webサイトの中で,あるページを見つける複数の手段がある
あるページを見つける手段が1つしかない
例:ある大手家電メーカーが提供するプリンター説明書ページには,以下の操作のみでアクセス可能
- トップページ:「製品情報」を選択
- 製品情報ページ:「個人向け」を選択
- 個人向け製品ページ:「PC周辺機器」を選択
- PC周辺機器製品ページ:「プリンター」を選択
- プリンター製品ページ:型番「PRT-123-4567」を選択
- 型番「PRT-123-4567」の製品ページ:「説明書」を選択
- やっと目的のものにたどり着けた
→検索機能を設置すべき
特に,視覚障害のある人は,画面を拡大しながらページを移動するよりも検索を好むかもしれない
→サイトマップを提供すべき
特に,認知障害のある人は,複数のページを移動するよりも全体を見渡せるマップを好むかもしれない
2.4.6 見出し及びラベル
見出しおよびラベルはわかりやすい
見出しやラベルがわかりにくい
<h2>今日の日記</h2>
<p>水族館に行った.魚がいっぱいいた</p>
<h2>日記</h2>
<p>進捗がゼロだった</p>
<h2> </h2>
<p>ねむい</p>
→見出しが本文を要約していない
→最後の見出しにテキストを入れ忘れている(おそらく眠かったため
利用者はサイトの構造をつかみにくい
ログインID:<input />
→ラベルはあるがわかりにくい
→IDってメールアドレスだっけ?その場合@
の前まで?後も必要?
注意:この基準とは別に,ラベルはUIコンポーネントのアクセシブルな名前として関連付けられると良い.詳しくは4.1.2 名前(name)・役割(role)及び値(value)を参照
見出しレベルが飛んでいる
<h1>岡山の歴史</h1>
<h3>紀元前</h3>
<p>耕作の発達した岡山県では…</p>
→例えばスクリーンリーダーの利用者は「見出しレベル2を読み飛ばしたかな?」と困惑する
2.4.7 フォーカスの可視化
キーボードで操作できるUIには,フォーカスインジケータがある
フォーカスインジケータを無効化している
<button>5億年</button>
<style>
/* クリックしたときの謎の枠線を消すためにつけてみた */
button {
outline: none;
}
</style>
→キーボードで操作できなくなる
フォーカスインジケータが見分けづらい
例:ユーザーの環境は「Ubuntu 22.04.1 LTS」のデフォルトである.この環境のフォーカスインジケータはオレンジ色である
ここでページのデザインに変更があり,背景がオレンジ色になったとする
<button>5億年</button>
<style>
body {
background-color: orangered;
}
</style>
→フォーカスインジケータは表示されているが,背景の色と似ているので見分けづらい
ページのデザインに合わせて,独自のフォーカスインジケータを作成してもいいかもしれない.
3. 理解可能(AA)
理解しやすいコンテンツを作ること
3.1 読みやすさ(AA)
読みやすいコンテンツを作ること
3.1.2 一部分の言語
コンテンツ内に別の言語がある場合,その言語が指定されている
固有名詞や技術用語に言語を指定する必要はない
言語が指定されていない
<!DOCTYPE html>
<html lang="ja">
<body>
<p>Linusは言った</p>
<blockquote>
<p>Given enough eyeballs, all bugs are shallow.</p>
<p>訳:大勢の目があれば,すべてのバグは大した問題ではない</p>
</blockquote>
</body>
</html>
→<p lang="en">Given enough eyeballs, all bugs are shallow.</p>
とするのが適切である
UAや支援技術の,表示や音声合成に対するヒントになる.
3.2 予測可能(AA)
コンテンツの挙動が予測可能であること
3.2.3 一貫したナビゲーション
繰り返されるナビゲーションはすべて一貫している
ページによってナビゲーションが変わる
例:ある市のサイトがある.トップページのナビゲーションは以下のようになっている
<nav>
<ul>
<li><a>観光地</a></li>
<li><a>よくある質問</a></li>
<li><a>今日の市長</a></li>
</ul>
</nav>
ここで,観光地を選択する.観光地のページのナビゲーションは以下のようになっている
<nav>
<ul>
<li><a>トップページ</a></li>
<li><a>今日の市長</a></li>
<li><a>よくある質問</a></li>
</ul>
</nav>
→順番が一貫していない
観光地リンクが消え,トップページリンクが現れた.「今日の市長」と「よくある質問」の順番が入れ替わった.
3.2.4 一貫した識別性
同じ機能のコンポーネントは一貫して識別できる
同じ機能なのに見た目が違う
<!-- あるページでは -->
<p>
<label>高評価する<button>⬆</button></label>
</p>
<!-- しかし別のページでは -->
<p>
<label>高評価する<button>👍</button></label>
</p>
<style>
button {
color: white;
background-color: black;
}
</style>
これは以下のように表示される
同じ機能なのにテキストが違う
<!-- あるページでは -->
<form>
<label>名前:<input /></label>
<button>送信</button>
</form>
<!-- しかし別のページでは -->
<form>
<label>好きな色:<input /></label>
<button>完了</button>
</form>
→どちらもフォームの送信ボタンだがテキストが異なる
同じ機能のUIに一貫性を持たせることで混乱を避け,また「慣れ」によって利用者の認知的負荷を軽減できる.
3.3 入力支援(AA)
間違いを防ぎ,修正を支援すること
3.3.3 エラー修正の提案
入力エラーの修正方法を提案できる場合,それが提示される
エラーの修正方法が不十分
<label>
<span style="color: red">使用できない文字が含まれています</span>
備考:<textarea aria-invalid="true"></textarea>
</label>
→どの文字が?
<label>
<span style="color: red">画像サイズが大きすぎます</span>
アイコン画像:<input aria-invalid="true" type="file" />
</label>
→どのサイズまでならOK?
<label>
<span style="color: red">パスワードが違います</span>
ログインパスワード:
<input aria-invalid="true" type="password" autocomplete="current-password" />
</label>
→修正方法がない
例えば
- 「パスワードをお確かめください」というメッセージと,パスワードを表示するボタンを設置する
- 「パスワードは英数字で記号を含みます」といったヒントを提示する
- 「パスワードリセットはこちら」というリンクを設置する
3.3.4 エラー回避(法的、金融、データ)
法的行為や金融取引が生じる操作には以下のいずれかの機能がある
- 操作を取り消せる
- 入力がチェックされ,不正な場合は修正できる
- 操作の完了前に利用者が内容を確認および修正できる
操作ミスが重大な結果を招く
例:あるオンラインバンキングサイトがある.ここでは資金の送金が行える
シナリオ:利用者は4,000円を別口座に送金したい.タッチパネルでWebサイトを操作している.以下の操作を行った
- 画面のテンキーを使用して「4」「0」「0」「0」と入力した
- 送金ボタンを押そうとしたが,誤って画面の「万」ボタンにも同時に触れてしまった
- 4,000万円の送金が即座に行われてしまった
→操作を取り消せると良かった
システムが実際の送金を行うのは,ボタンが押されてから10分後というようにして,一定時間内なら取り消しできると良かった
→入力がチェックされると良かった
一定以上の金額には,「金額が大きいです.本当に送金しますか?」といったダイアログが表示されると良かった
→確認画面があれば良かった
送金前に「内容を確認してください」という画面があればキャンセルできた
4. 堅牢(AA)
様々なUAが解釈できるように,堅牢なコンテンツを作成すること
4.1 互換性(AA)
様々なUAとの互換性を最大化すること
4.1.3 ステータスメッセージ
ステータスメッセージは解釈可能で,利用者はそれにフォーカスしなくても認識できる
ステータスメッセージが解釈可能でない
例:あるブログサイトでは保存ボタンを押すと,画面左下に「成功しました」というメッセージ(スナックバー)が一定時間表示される
<form>
<label>日記:<textarea></textarea></label>
<button type="button">保存</button>
</form>
<div>成功しました</div>
<style>
/* 省略 */
</style>
<script>
// 省略
</script>
すべてのコード
<form>
<label>日記:<textarea></textarea></label>
<button type="button">保存</button>
</form>
<div>成功しました</div>
<style>
div {
display: none;
position: absolute;
bottom: 1em;
left: 1em;
padding: 1em;
border: 1px solid black;
}
</style>
<script>
const snackbar = document.querySelector("div");
const saveButton = document.querySelector("button");
saveButton.addEventListener("click", () => {
snackbar.style.display = "block";
setTimeout(() => {
snackbar.style.display = "none";
}, 2000);
});
</script>
→目の見えない人は「保存しました」のメッセージに気づけない
<div role="status" aria-live="polite">成功しました</div>
が正しい
ステータスメッセージがうるさい
例:ある広告がrole="alert"
およびaria-live="assertive"
を使用している
→スクリーンリーダーは重要でない情報を優先して読み上げてしまう
レベルAAA
最高のアクセシビリティを提供するなら失敗したくない,プロ用のレベル.コンテンツによっては,そもそも達成不可能な基準も2
1. 知覚可能(AAA)
ユーザーがコンテンツを知覚(見る,聞く,触る…)できること
1.2 時間依存メディア(AAA)
時間依存のメディアに代替があること
1.2.6 手話(収録済)
収録済みの動画の,音声トラックに手話通訳がある
音声に手話通訳がない
→自然言語がキャプションの言語と異なる人は,それを十分に理解できないかもしれない
→自然言語が手話である人は,キャプションが読めないかもしれない
1.2.7 拡張音声解説(収録済)
音声解説だけでは映像の意味を伝達しきれない場合,拡張音声解説が提供されている
拡張音声解説が提供されていない
例:ある数学の動画教材がある.教師が黒板を使いながら問題を解説している.板書は音声解説で提供されているが,それだけである.
→問題の合間に動画を一時停止し,拡張音声解説を入れるのが望ましい
目の見える人は黒板を見ながら教師の説明を聞ける.一方で見えない人はそれができない.板書を一度読み上げられても,それを覚えておける量には限界がある.したがって一時停止しての解説が必要.
1.2.8 メディアに対する代替(収録済)
収録済みの音声および映像には代替(書き起こし)がある
注意:音声解説によって「1.2.3 音声解説、又はメディアに対する代替(収録済)」と「1.2.5 音声解説(収録済)」を達成していた場合は,新たに代替も作成する必要がある
代替がない
例:一発ギャグ大会の動画があるが,代替は提供されていない.
→目が見えず耳も聞こえない人は一発ギャグを楽しめない
例えば台本のような書き起こしを提供すれば,点字ディスプレイなどで読める
1.2.9 音声のみ(ライブ)
ライブ音声配信にキャプションや代替がある
ライブ音声配信にキャプションや代替がない
例:漫談の音声をライブ配信しているサイトがある.しかしキャプションが提供されていない
→キャプションを提供する.以下のような方法が考えられる
- ライブが台本通りに進んでいるなら,台本のテキストを提供
- 速記を用いた高速入力技術
- 高速タイピング技術(ステノキャプショナー)
- 音声認識技術(ライブ音声を入力する,またはライブ音声を人間が聞き取って復唱し入力する)
1.3 適応可能(AAA)
様々な環境にコンテンツが適応できること
1.3.6 目的の特定
コンテンツ(UIコンポーネント,アイコン,領域など)の目的は解釈可能
目的が解釈可能でない
<form><input /><button>検索</button></form>
→<form role="search">
が適切
<main>
<h1>日記:2022/09/28</h1>
</main>
<main>
<h1>日記:2022/09/27</h1>
</main>
→ページに複数のmain
ランドマークがあるべきでない
<ul>
<li><a>トップページ</a></li>
<li><a>製品情報</a></li>
<li><a>会社情報</a></li>
<li><a>お問い合わせ</a></li>
</ul>
→nav
要素を用いてナビゲーションロールをつけるべき
<div>相互リンク集</div>
→role="complementary"
によって補足情報であることを明示すると良い
まとめると,コンテンツの目的を示すことは以下のことに役立つ
- ナビゲーション
- 例:ヘッダーなどをスキップして
main
ランドマークに移動する
- 例:ヘッダーなどをスキップして
- 簡素化
- 例:
main
以外の要素を隠して表示する
- 例:
- 追加情報の提示
- 例:語彙が限られる人などが好むシンボルを追加で提示する(以下画像参照.将来的には,
data-symbol
などによる意味の提示によって,UAは利用者それぞれが好むシンボルを表示できるかもしれない)
- 例:語彙が限られる人などが好むシンボルを追加で提示する(以下画像参照.将来的には,
以下は追加情報を提示する前のページ
以下はページにシンボルを追加した状態
以下は,先程のページを別のシンボルセットで表示している状態.利用者それぞれが好むシンボル画像でページを利用できる.
画像の出典: 1.2.4.1 Proof of Concept: Symbol Example - WAI-Adapt Explainer
1.4 判別可能(AAA)
コンテンツを見やすいものにすること.
1.4.6 コントラスト(高度)
サイズの大きなテキストに,4.5:1以上のコントラストがある
「サイズの大きなテキスト」の定義は1.4.3 コントラスト(最低限)の説明を参照.
そうでないテキストに,7:1以上のコントラストがある
この基準は,1.4.3 コントラスト(最低限)の強化版である.基準となるコントラスト比の閾値が引き上げられている.
十分なコントラスト比がない
コードを見る
<p>
<span class="normal">normal size text</span>
<span class="normal">normal size bold text</span>
<span class="normal">通常サイズの文字</span>
<span class="normal">通常サイズの太字</span>
<span class="big">big size text</span>
<span class="big">big size bold text</span>
<span class="big">サイズの大きな文字</span>
<span class="big">サイズの大きな太字</span>
</p>
<style>
.normal {
color: #211512;
background: #a1a1a1;
}
.big {
color: #f8e45c;
background: #ad4800;
}
span:nth-of-type(1) {
font-size: 16px;
}
span:nth-of-type(2) {
font-size: 14px;
font-weight: bold;
}
span:nth-of-type(3) {
font-size: 20px;
}
span:nth-of-type(4) {
font-size: 16px;
font-weight: bold;
}
span:nth-of-type(5) {
font-size: 24px;
}
span:nth-of-type(6) {
font-size: 19px;
font-weight: bold;
}
span:nth-of-type(7) {
font-size: 29px;
}
span:nth-of-type(8) {
font-size: 24px;
font-weight: bold;
}
span {
padding: 1em;
}
p {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
</style>
→通常サイズのテキストのコントラスト比は6.88:1であり,基準を下回っている.
→サイズの大きなテキストのコントラスト比は4.38:1であり,基準を下回っている
1.4.7 小さな背景音、又は背景音なし
収録済みの発話で音楽表現を意図していないもの(例:ポッドキャストなど)は以下のいずれかである
- 背景音(BGMなど)を含まない
- 背景音を消せる
- 背景音は発話よりも20デシベル以上低い
BGMが大きすぎて発話が聞き取れない
音声サンプルは公式のものを参照
出典: 非発話音が発話音声コンテンツより少なくとも 20 デシベル低くなるように、音声ファイルを編集する
1.4.8 視覚的提示
テキストブロックは以下を満たす
- 利用者が前景色と背景色を選択できる
- 幅が80文字(全角文字の場合は40文字)を超えない
- 均等割り付け,両端揃えされていない
- 行送りが少なくとも1.5文字分ある
- 段落の間隔が行送りの1.5倍以上ある
- テキストは200%まで拡大でき,利用者の全画面表示で横スクロールが発生しない
文字数,行間,段落の間隔が適切でない
<p>
「初カキコども」は,2ちゃんねるのオカルト板への書き込み.今や伝説のコピペである.
</p>
<p>
初カキコ…ども…
俺みたいな中3でグロ見てる腐れ野郎、他に、いますかっていねーか、はは
今日のクラスの会話 あの流行りの曲かっこいい とか あの服ほしい とか
ま、それが普通ですわな かたや俺は電子の砂漠で死体を見て、呟くんすわ it’a
true wolrd.狂ってる?それ、誉め言葉ね。 好きな音楽 eminem
尊敬する人間 アドルフ・ヒトラー(虐殺行為はNO)
なんつってる間に4時っすよ(笑) あ~あ、義務教育の辛いとこね、これ
</p>
<style>
p {
width: 50em;
line-height: 1;
margin: 0.5em 0;
padding: 0;
}
</style>
→幅が約50文字ある
改行を追うのが難しい人もいるかもしれない
→行間が狭すぎる,もしくは無い
これも改行を追いづらくする要因である
→段落間が近すぎる
読者は段落が変わったことに気づけないかもしれない
均等割り付け,両端揃えされている
<p>
my first time writing... Guys... Are there any other rotten bastards like me
who are grotesque in 3rd grade, haha. today's class conversation. That trendy
song is cool or that girl who wants that dress. oh that's normal. On the other
hand, when I see a corpse in the electronic desert, I mutter. it's a true
world. Am I crazy? That's a compliment. Favorite music: eminem. Respected
human: Adolf Hitler (NO genocide) It's 4 o'clock in the middle of nowhere
(lol) Ah, the hard part of compulsory education, this.
</p>
<style>
p {
text-align: justify;
line-height: 1;
}
</style>
→普通に左揃えで表示すべき
人によっては,特に認知に障害のある人には,リバー(白い川とも)が認識の邪魔になってしまう.
前景色および背景色を変える方法がわからない
→例えば,変更方法を示した説明を追加する
説明の例:ChromeとFirefoxではStylusというアドオンで色を変更できます
1.4.9 文字画像(例外なし)
文字画像ではなくテキストが用いられている
ただし,必要不可欠なものは例外
→必要不可欠な例は,1.4.5 文字画像を参照
この基準は,1.4.5 文字画像の強化版である.
1.4.5では文字画像の見た目をカスタマイズできる場合に例外が認められていた.しかし本基準では認められない.
文字画像が用いられている
→失敗例は1.4.5 文字画像を参照
2. 操作可能(AAA)
UIコンポーネントは操作可能でなければならない
2.1 キーボード操作可能(AAA)
キーボードで操作できること
2.1.3 キーボード(例外なし)
コンテンツのすべての機能はキーボードで操作できる
この基準は,2.1.1 キーボードの強化版である.
2.1.1には例外事項があったが,本基準にはない.したがって,軌跡に依存する機能はそもそもこの基準を達成不可能である.
キーボードで操作できない機能がある
→失敗例は2.1.1 キーボードを参照
2.2 十分な時間(AAA)
コンテンツを読み,使用する十分な時間があること
2.2.3 タイミング非依存
コンテンツに制限時間がない
制限時間がある場合,次のいずれかである
- リアルタイムのイベント(例:オークション)
- 制限時間が必要不可欠
この基準は,2.2.1 タイミング調整可能の強化版である.制限時間の例外は,リアルタイムまたは必要不可欠な場合に限られる.
リアルタイムでも必要不可欠でもないコンテンツに制限時間がある
→失敗例は2.2.1 タイミング調整可能を参照
2.2.4 割り込み
緊急を要さない割り込みは,抑制または停止できる
割り込みが抑制または停止できない
例:為替情報を提供するページがある
<!-- 為替レートが数秒ごとにJavaScriptでリアルタイム更新される -->
<span role="alert" aria-live="assertive">
現在の為替レートは,144.31 JPY/USD
</span>
<h2>今週の為替状況</h2>
<p>今週は特に大きな動きがありました.それは……</p>
→例えばスクリーンリーダーで本文を読んでいる最中に,更新された情報が割り込んで読まれてしまう
更新を一時停止するような仕組みが望ましい
2.2.5 再認証
認証セッションが切れた場合でも,データを失うことはない
セッションが切れた場合にデータを失ってしまう
例:航空券の購入
- 認知障害をもつ利用者が航空券購入の長いフォームを進めている
- 障害のため入力に時間がかかったが,なんとか「購入」ボタンを押した
- しかしセッションが切れてしまっており,ログイン画面にリダイレクトされた
- ログインすると同じフォーム画面に戻ってきた
- しかし,入力内容は消えていた
→入力内容が失われないような仕組みを実装すべき
2.2.6 タイムアウト
利用者の無操作によってデータが失われる可能性がある場合は,それが警告される
または,無操作のタイムアウトが20時間以上
タイムアウト時間が書かれていない
<fieldset>
<legend>どちらかに投票してください</legend>
<label><input type="radio" name="vote" />テツ</label>
<label><input type="radio" name="vote" />トモ</label>
</fieldset>
<p>※プライバシー保護のため,一定時間以内に送信されない回答は破棄されます</p>
→具体的にどれくらいの時間でタイムアウトするのか書くべき
2.3 発作と身体的反応(AAA)
発作を起こすようなコンテンツは作成しないこと
2.3.2 3 回の閃光
どの1秒間にも3回の閃光を放つものがない
ここでは基準 2.3.1 3回の閃光、又は閾値以下で許可されていた閾値が無い
1秒間に3回の閃光を放つものがある
例:ユーザーの注意をひくための点滅する広告など
2.3.3 インタラクションによるアニメーション
インタラクションによるアニメーションを無効化できる
インタラクションによるアニメーションが必要不可欠である
不要なパララックス効果
例:カレーのランディングページがある.画面をスクロールすると,カレーライスのイラストが近づいたり離れたり,無数のにんじんが視差効果を生み出したり,宣伝文が横から飛び出たりする.
→アクセシビリティの観点からはパララックスをやめるべき.または効果を必要なもののみに抑えるべき
余計な動きは,特に前庭障害を持つ人へ大きく影響する.コンテンツに集中できなかったり,ひどい場合には回復のためにベッドでの安静が必要になったりする.
2.4 ナビゲーション可能(AAA)
利用者がサイト内で迷わないこと
2.4.8 現在位置
サイト内で利用者の位置に関する情報が利用できる
現在位置を示す情報がない
例:プリンターの説明書を探している
- 利用者は,「PRT-123-4567」の説明書を探している
- 検索エンジンの結果,「PRT-122-4567」の説明書が見つかった.これは探しているものとは微妙に違う.
- 利用者は1つ上の階層のページに行こうと考えたが,そもそも現在ページがどこなのかわからなかった
→例えばパンくずリストが提供されていればよかった
パンくずリストの例:「製品情報 > 個人向け > PC周辺機器 > プリンター > PRT-122-4567」
2.4.9 リンクの目的(リンクのみ)
リンクのテキスト単独で,その目的が判断できる
リンクのテキスト単独で,その目的が判断できない
<a>ダウンロードする</a>
→何を?
<a>今年度決算報告書(Word)</a> <a>PDF版</a>
→何のPDF版?
<a>ここをクリック</a>するとヘルプが開きます
→「ここをクリック」するとどうなる?リンクテキスト単独では判断できない
2.4.10 セクション見出し
セクションには見出しがある
見出しが無い
<form><input /><button>岡山の情報を検索</button></form>
<p>岡山県の首都について,岡山市は日本の政治,経済,国防など……</p>
<p>岡山の歴史について,紀元前,太古の岡山県民は……</p>
→見出しをつけるべき
上記のフォームと段落はそれぞれが独立したセクションとみなせる.それぞれの直前に見出しを配置できる.
これは非常に重要なことである.多くの利用者がコンテンツを流し読みするという調査結果がある.また,約67%のスクリーンリーダー利用者は,見出しによって情報を見つけるという調査結果もある.これは検索機能やランドマークに比べて高い数字である.
2.5 入力モダリティ(AAA)
様々な入力機器で操作しやすいこと
2.5.5 ターゲットのサイズ
ポインタ入力のターゲットサイズは44px × 44px以上
ただし以下は例外
- 同じ機能の大きいボタンがある
- インラインである:リンク,文中のボタンなど
- UAが提供する機能をそのまま使っている
- 必要不可欠
ターゲットが小さい
<p>このボタンは,それを操作するには狭すぎる</p>
<button>狭い</button>
<style>
button {
width: 43px;
height: 43px;
}
</style>
これは以下のように表示される
→特にタッチ操作は精度が荒い入力方法である.このサイズだとギリギリ操作が難しい人もいるかもしれない
2.5.6 入力メカニズム非依存
コンテンツが入力方法を制限しない
コンテンツが入力方法を制限している
例1:不十分なファストタップの実装
<div>乱数:<span></span></div>
<button>更新</button>
<script>
const span = document.querySelector("span");
const button = document.querySelector("button");
// これだとスマホで遅い
// button.addEventListener("click", () => (span.innerText = Math.random()));
// これだと早い!
button.addEventListener("touchend", () => (span.innerText = Math.random()));
</script>
→マウスで操作できない
補足:このファストタップの実装は簡易的なため,2.5.2 ポインタのキャンセルにも失敗する
例2:例1をマウス・キーボードにも対応させた
<div>乱数:<span></span></div>
<button>更新</button>
<script>
const span = document.querySelector("span");
const button = document.querySelector("button");
if (window.TouchEvent || "ontouchend" in window) {
// タッチスクリーン用
button.addEventListener("touchend", () => (span.innerText = Math.random()));
} else {
// マウス・キーボード用
button.addEventListener("click", () => (span.innerText = Math.random()));
}
</script>
それでもなお,以下のようなケースで問題がある
ケース1:タッチ操作が可能なPCを使用している
→キーボードで操作できない
ケース2:タブレットに外付けのキーボードを接続した
→やはりキーボードで操作できない
ケース3:ページ読み込み後に,外付けのタッチスクリーンを接続した
→タッチ操作できない
ケース4:ページ読み込み後に,外付けのタッチスクリーンを切断した
→ページをリロードするまで,ボタンを操作する方法はない
3. 理解可能(AAA)
理解しやすいコンテンツを作ること
3.1 読みやすさ(AAA)
読みやすいコンテンツを作ること
3.1.3 一般的ではない用語
一般的でない単語の定義を特定できる
単語の定義が特定できない
<h2>障害のお知らせ</h2>
<p>
現在サービスが使用不可能な状態です.ソースコードのバージョン管理を誤り,一部の機能が先祖返りしています
</p>
→「ソースコード」「バージョン管理」「先祖返り」は,専門家でない読者には伝わらない
ページの最後に用語集を定義し,そこに単語をリンクさせると良い.
(もっとも,一般向けの説明には専門用語を極力使用しないと良い)
3.1.4 略語
略語のもとの語を特定できる
略語のもとの語がわからない
<p>
DDDは新しいソフトウェア開発手法である.締切が間近である人間のアドレナリンを利用して効率を高める.
</p>
→「DDD」が何の略なのか示されていない
例えば,「DDD(deadline-driven development)は新しいソフトウェア開発手法である」というように,初出の際に説明する.またはaddr
属性を用いても良い.
3.1.5 読解レベル
固有名詞や題名を取り除いた文章は,中学3年生にも理解できる
または,中学3年生でも理解できるバージョンが提供されている
文章が簡潔でない
例:「美味しいコーヒーの淹れ方」というページには以下の説明がある
必要な器具をあらかじめ温めたうえで水素と酸素の化合物であるDHMOを95度まで加熱しペーパーフィルターの底と側面の接着部分を折ってドリッパーに軽く押さえつけるようにセットしフィルターにコーヒー粉を入れた上でドリッパーを軽く降って粉の表面を平らに均し少量の加熱されたDHMOを乗せるように注ぎ入れて20秒ほど蒸らし待つとサーバーに抽出物がポタポタとたれてくるのが確認できるためコーヒー粉の中心に小さな「の」の字を描くように加熱されたDHMOを3回に分けてまず80cc次に40cc最後に20ccと注ぎ抽出物をカップに注ぎ入れたら完成
→読みにくい
一文が長い,句読点がない,言い回しが難しいなどの要因が考えられる.
この文章が中学3年生に理解可能であるかを定量的にテストすることは難しい課題だが,いくつかの研究やツールが存在する.
- 建石由佳, 小野芳彦, and 山田尚勇. "日本文の読みやすさの評価式." 情報処理学会研究報告ヒューマンコンピュータインタラクション (HCI) 1988.25 (1988-HI-018) (1988): 1-8.
- textstat-plugin-ja
- 日本語リーダビリティー測定 Ver.0.2 - リーダビリティ・リサーチ・ラボ
3.1.6 発音
発音がわからないと単語の意味が不明瞭になる場合,発音を特定できる
発音がわからない
<p>とある魔術の禁書目録は,日本のライトノベルである</p>
<p>主人公である上条当麻は,とある事件に巻き込まれる</p>
→「禁書目録」および「上条当麻」の読みを提供すべき
タイトルと主人公の名前は作中に頻出する.特に言語障害のある人や音声読み上げを利用している人にとって有用である.
「禁書目録(インデックス)」のように読みをカッコ書きするか,またはruby
要素を利用できる.
3.2 予測可能(AAA)
コンテンツの挙動が予測可能であること
3.2.5 要求による変化
利用者の意図しないコンテキスト変化がない
または,利用者の意図しないコンテキストの変化を止める仕組みがある
ここでの「利用者の意図しないコンテキストの変化」とは,例えば以下のようなものである
- 例:UIコンポーネントにフォーカスするとダイアログが出る(3.2.1 フォーカス時(レベルA)を参照)
- 例:UIコンポーネントの設定を変えるとフォームが送信されてしまう(3.2.2 入力時(レベルA)を参照)
- 例:ページの自動リダイレクト,自動リロードがある(2.2.1 タイミング調整可能(レベルA)を参照)
本基準では,上記を含むすべての意図しないコンテキストの変化を禁止している
利用者の意図しないコンテキストの変化があり,それを止められない
3.3 入力支援(AAA)
間違いを防ぎ,修正を支援すること
3.3.5 ヘルプ
コンテキストに応じたヘルプが利用可能
ヘルプが利用できない
例:年末調整を行うフォームがある
<label>源泉控除対象配偶者の氏名:<input /></label>
→利用者によっては「源泉控除対象配偶者」がわからないかもしれない.この用語を説明するヘルプリンクを設置すると良い
例:サーバーのCPU使用率やネットワークトラフィック量など,インフラ業務のためのダッシュボードがある.特にヘルプ機能はない
→初めての利用者のために,使い方をまとめたドキュメントへのリンクがあると良い
→または,画面を実際に操作しながら使い方を学ぶ「ヘルプツアー」機能があっても良い
3.3.6 エラー回避(すべて)
利用者が情報を送信する操作には以下のいずれかの機能がある
- 操作を取り消せる
- 入力がチェックされ,不正な場合は修正できる
- 操作の完了前に利用者が内容を確認および修正できる
この基準は,3.3.4 エラー回避(法的、金融、データ)の強化版である.
3.3.4 エラー回避(法的、金融、データ)では,対象となる操作は,法的行為や金融取引などの重要なものに限定されていた.しかし本基準では,情報を送信するすべての操作が対象である.
操作ミスを取り返せない
→失敗例は3.3.4 エラー回避(法的、金融、データ)を参照
おわりに
正直に言って,WCAGへの適合はレベルAであっても大変だし,追加コストもかかります.例えば動画を埋め込んでいる場合,レベルAでは「キャプションと音声解説か代替用意しろ」とあります.我々コンテンツの作り手としては 「え?字幕用意するの?この動画プレーヤーって字幕対応してたっけ……?音声解説?誰が読み上げるんだ?声優を雇うのか?合成音声でもいいのか?あ,もしくは書き起こしか?ビジュアルデザインは……」 と,おおわらわです.
一方で,そこまでコストがかからない達成方法もあります.例えば「装飾画像のalt
には空文字を指定する」は,知ってたら2秒でコード書いて終わりです.
しかしその効果は小さくありません.私は実際にスクリーンリーダーを使ってみて実感しました.よくわからん枠線で毎回「ラベルのない画像」とか「枠線画像」などと読まれるのはシンプルにストレスです.それがなくなるだけでも体験は格段に良くなります.
というわけで「まずはできるところから3」というのがコスパの良い方針ではないでしょうか.例えばこの記事で「やっちゃダメなこと」が認知され,それで世の中が少しでもアクセシブルになるなら嬉しいです.
まだまだアクセシビリティ初心者なので,間違いを見つけた場合はマサカリをお願いします.
素材の出典
- 増加するグラフ - パブリックドメインQ
- キャッシュバック - パブリックドメインQ
- アイスと星マーク - パブリックドメインQ
- カレーライス - パブリックドメインQ
- プレゼンする社員とグラフ - パブリックドメインQ
- みんなの公共サイト運用ガイドライン(2016年版)によれば,「適合レベル AA に準拠していないホームページ等」について「速やかに、ウェブアクセシビリティ方針を策定・公開し、遅くとも 2017 年度末までに適合レベル AA に準拠」とある↩
- 適合を理解するによれば「コンテンツの中には、レベル AAA 達成基準のすべてを満たすことのできないものもあるため、サイト全体の一般的な方針としてレベル AAA での適合を要件とすることは推奨されない。」↩
- まぁ私は一般企業のエンジニアなのでこんなことが言えます.公共サイトではAA適合が推奨されているので,対応されているエンジニアの方々には頭が上がりません↩