アクセシビリティ対応は「特別な利用者のための追加作業」と受け取られがちですが、業務システムでは事情が違います。キーボードだけで完結する画面は、全員にとって速い画面です。対応の主目的は生産性向上だと考えたほうが、社内の合意も取りやすくなります。
日本では JIS X 8341-3:2016(WCAG 2.0 と整合)が広く参照され、公共調達などでは適合レベルの明示を求められることがあります。新規開発では最新の WCAG 2.2 レベルAA を目標にしておくと、後追いの改修が減ります。
まず押さえるべき7項目
| # | 要件 | 具体的な基準 |
|---|---|---|
| 1 | コントラスト比 | 本文4.5:1以上、UI部品3:1以上 |
| 2 | キーボード操作 | すべての機能がキーボードだけで実行できる |
| 3 | フォーカスの可視化 | フォーカスリングを消さない。コントラスト3:1以上 |
| 4 | ラベルの関連付け | すべての入力欄に label を紐づける |
| 5 | 色だけに依存しない | 状態は色+文言/アイコンで伝える |
| 6 | 見出し構造 | h1→h2→h3 の順序を飛ばさない |
| 7 | 代替テキスト | 画像・アイコンボタンに alt / aria-label |
この7つを満たすだけで、実務上の指摘の大半は解消します。
キーボード操作の設計
基本のキー割り当て
| キー | 期待される動作 |
|---|---|
| Tab / Shift+Tab | 次/前の操作可能要素へ移動 |
| Enter | ボタンの実行、リンクの遷移、検索欄での検索実行 |
| Space | ボタンの実行、チェックボックスの切り替え |
| Esc | モーダル・ドロップダウンを閉じる |
| ↑ ↓ | 一覧の行移動、セレクトの候補移動 |
| Home / End | 先頭・末尾へ移動 |
<div onclick> でボタンを作ると、Tabで到達できず、Enterでも実行できません。ボタンは <button>、遷移は <a href> を使う。これだけでキーボード対応の8割が自動的に満たされます。
フォーカスリングを消さない
outline: none は、業務システムにおける最も破壊的な1行です。デザイン上どうしても既定のリングが合わない場合は、代替のスタイルを必ず用意します。
/* NG */
:focus { outline: none; }
/* OK:マウス操作時は控えめに、キーボード操作時は明示 */
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 2px;
}
スキップリンク
サイドメニューの項目が多い画面では、Tabキーで本文にたどり着くまでに数十回の操作が必要になります。画面先頭に「本文へスキップ」リンクを置いてください。
<a class="skip-link" href="#main">本文へスキップ</a>
フォームのマークアップ
- `label` の `for` と入力欄の `id` を必ず対応させる(ラベルクリックでフォーカスが入る)
- 必須は `required` 属性と視覚表現の両方で示す
- エラーは `aria-invalid="true"` と `aria-describedby` でメッセージと紐づける
- 関連する項目群は `fieldset` + `legend` でまとめる
- プレースホルダーをラベルの代用にしない
<label for="delivery-date">納品日<span class="req">必須</span></label>
<input id="delivery-date" name="deliveryDate" type="text"
required aria-invalid="true" aria-describedby="delivery-date-error">
<p id="delivery-date-error" class="field-error">
納品日は受注日(2026/05/18)以降を入力してください。
</p>
動的な変更を伝える
トーストや検索結果の更新は、画面を見ていない利用者には伝わりません。ライブリージョンを使います。
<!-- 検索結果件数など:操作を妨げず読み上げる -->
<div aria-live="polite" id="result-status">1,248件中 1〜50件を表示</div>
<!-- エラーなど緊急性が高いもの -->
<div aria-live="assertive" role="alert" id="global-error"></div>
aria-live="assertive" を多用すると、読み上げが割り込み続けて操作不能になります。assertive はエラーだけ、それ以外は polite を使ってください。
ARIAは「使わない」が最初の選択肢
ネイティブのHTML要素で表現できるなら、ARIAは使わない。role="button" を付けた div より、素の <button> のほうが常に正しく動きます。
ARIAが必要になるのは、タブ・ツリー・コンボボックスなどHTMLに対応する要素がない部品を自作する場合だけです。
WCAG 2.2 で追加された注目の項目
- フォーカスの非遮蔽:固定ヘッダーやフッターでフォーカス中の要素が隠れないこと。スティッキー要素の多い業務システムでは要注意
- ドラッグ操作の代替:並べ替えなどのドラッグ操作に、クリックやキー操作の代替手段を用意すること
- ターゲットサイズ(最小):クリック可能領域は24×24px以上(例外あり)
- 冗長な入力の回避:同じ情報を再入力させない。自動入力または選択で補う
- アクセシブルな認証:ログイン時に記憶やパズルを必須にしない
検証の進め方
マウスを外して1業務を通す
最も効果的な検証です。受注入力から登録完了まで、キーボードだけで到達できるかを確認します。詰まった場所がそのまま課題リストになります。
自動チェックツールを通す
axe DevTools や Lighthouse で機械的に検出できる不備(コントラスト、ラベル欠落、見出し構造)を潰します。ただし自動検出で見つかるのは全体の3〜4割程度です。
拡大表示で確認する
ブラウザのズームを200%にして、レイアウトが破綻せず操作できるかを確認します。業務システムでは実際に拡大して使っている利用者がいます。
スクリーンリーダーで主要画面を確認
NVDA(Windows)やVoiceOver(macOS)で、ログイン・一覧・入力の3画面だけでも通してみると、実装の穴が具体的に見えます。
チェックポイント
- マウスを使わずに一連の業務が完了できる
- フォーカスリングが消されていない
- ボタンが `button`、遷移が `a` で実装されている
- すべての入力欄に label が関連付けられている
- エラーが aria-describedby でメッセージと結びついている
- 固定ヘッダーでフォーカス中の要素が隠れない
- 200%拡大しても操作できる