WCAG 達成基準 · Level A
WCAG 2.1.4: 文字キーのショートカット
WCAG 2.1.4 は、単一の文字キー(文字、数字、句読点、または記号)のみを使用して実装されたあらゆるキーボードショートカットについて、それをオフにする、再割り当てする、またはフォーカス時にのみ有効化できるようにすることを求めています。これは、音声入力に依存しているユーザーや運動障害のあるユーザーに害を及ぼす偶発的なトリガーを防ぐためです。
- Level A
- Wcag
- Wcag 2 2 a
- 操作可能
- アクセシビリティ
このルールの意味
WCAG 2.1.4「文字キーのショートカット」は、WCAG 2.1 で導入されたレベルAの達成基準です。これは、ウェブアプリケーションが、Ctrl、Alt、Meta、Shift などの修飾キーを併用せずに、単一の印字可能な文字(文字、数字、句読点、記号)だけで構成されるキーボードショートカットを割り当てる場合に生じる、特定だが重大なアクセシビリティ上の危険に対処するものです。
この達成基準では、コンテンツ内で単一の文字キーだけを用いたキーボードショートカットが実装されている場合、少なくとも次のいずれかが真でなければならないと定めています。
- オフにできる: ユーザーがショートカットを完全にオフにできる仕組みが用意されている。
- 再割り当てできる: ユーザーがショートカットを、1つ以上の非印字の修飾キー(Ctrl や Alt など)を使うように再割り当てできる仕組みが用意されている。
- フォーカス時のみ有効: ユーザーインターフェイスコンポーネントのキーボードショートカットは、そのコンポーネントにフォーカスがあるときにのみ有効である。
単一文字キーショートカットとは、印字可能な文字を生成する単一のキーを押すことで起動されるものを指します。たとえば、ギャラリーを開くために G を押す、検索バーにフォーカスするために / を押す、新しいメッセージを作成するために N を押す、といったものです。これらは、Ctrl+S や Alt+F4 のように非印字の修飾キーを必要とするショートカットとは本質的に異なり、そのためこの達成基準の対象外となります。
ショートカットがこの達成基準に適合するのは、アプリケーションが次のいずれかを行っている場合です。(1) 単一キーショートカットを無効化したり複数キーの組み合わせに変更したりできる設定・環境設定ページを提供している。(2) 自動的に修飾キーを伴うショートカットに再割り当てしている。(3) トリガーとなる要素自体にキーボードフォーカスがあるときにのみショートカットが発火する — つまり、フォーカスが別の場所にある状態でキーを押しても何も起こらない。
ショートカットが不適合となるのは、単一文字のキー入力が、どの要素にフォーカスがあるかに関係なく常にグローバルなアクションを発火させ、かつユーザーがそれをオフにしたり変更したりする手段がない場合です。よくある実例として、ユーザーが文字キーを押すたびにナビゲーションアクションが発火するシングルページアプリケーションが挙げられます。これは、ユーザーがテキストフィールドに入力している最中や音声入力でテキストを入力している最中であっても同様です。
この達成基準には、1つ重要な公式の例外が含まれています。それは、ショートカットが特定のコンポーネントにフォーカスがある間にのみ有効な場合には適用されない、というものです。たとえば、ドロップダウン自体が開いてフォーカスされているときにのみ文字キーを受け付けるカスタムドロップダウンウィジェットは、フォーカスの制限によって誤作動のリスクが抑えられているため、許容されます。
なぜ重要か
この達成基準は主に2つのユーザーグループを保護するために存在しますが、その恩恵はさらに広く及びます。
音声入力ユーザーが最も直接的な影響を受けます。運動障害のある人は、Dragon NaturallySpeaking(現在の Dragon Professional)などの音声認識ソフトウェアを使って、コンピューターを完全に音声だけで操作していることがあります。テキストを口述したり音声コマンドを発したりするとき、これらのツールはキーストロークを発生させ、アクティブなウェブページ上の単一文字ショートカットを意図せずトリガーしてしまうことがあります。たとえば、ユーザーが医療フォームにテキストを口述していて「next」と言ったとします。アプリケーションがグローバルに文字 N を監視していると、そのフォームから離れるナビゲーションが発生し、ユーザーの作業が失われるかもしれません。CDC によると、米国の成人約 61 百万人が何らかの障害を抱えており、その相当数が音声認識を含む代替入力手段に依存しています。
運動障害のあるユーザーで、スイッチアクセス、シップ・アンド・パフ装置、キーボードのみのナビゲーションを使用している人もリスクにさらされています。これらのユーザーは、誤ってキーを押してしまったり、目的のキーに到達しようとして複数のキーをなぞるように押してしまったりすることがあります。メールのアーカイブ、ファイルの削除、フォームの送信など、取り消し不能なアクションを単一の誤操作でトリガーしてしまうと、大きなフラストレーションやデータ損失につながります。
認知障害のあるユーザーも被害を受ける可能性があります。注意欠如障害のあるユーザーや、インターフェイスに不慣れなユーザーは、ページを探索するために試しにキーを押してみることがあり、単一文字ショートカットが有効になっていることに気づいていないかもしれません。予期しないナビゲーションや状態変化は、認知的負荷や混乱を増大させます。
次のような実際のシナリオを考えてみてください。あるトルコのECプラットフォームが、パワーユーザー向けに単一キーショートカットを実装しています — ショッピングカートに移動するために C を押す、お気に入りに移動するために F を押す、といった具合です。音声入力ユーザーが、フォームフィールドに配送先住所を口述しようとします。「Caddesi」(トルコ語で「通り」を意味する)と言ったとき、フォーカスが完全に入力欄に入る前に音声ソフトウェアが文字 C を送出し、カートページへのナビゲーションがトリガーされます。途中まで入力していた住所は失われます。ユーザーは最初からやり直さなければならず、この経験が繰り返されれば、そのサイトを完全に離れてしまうかもしれません。
アクセシビリティの観点を超えても、この達成基準への対応は全体的なユーザビリティを向上させます。ショートカットのカスタマイズUIを提供することは、成熟したユーザー尊重型のプロダクトであることのシグナルになります。また、誤ってショートカットを発動させてしまったユーザーからのサポート問い合わせを減らすことにもつながります。
関連する Axe-core のルール
WCAG 2.1.4 には手動テストが必要です。なぜなら、自動ツールではすべての単一文字キーボードショートカットを確実に検出したり、再割り当て/無効化の仕組みが存在するかどうかを検証したりすることができないからです。ここでは、自動化が不十分な理由と、テスターが手動で確認しなければならない点を説明します。
- 専用の axe-core ルールは存在しない(手動チェックが必要): Axe-core や Lighthouse には、単一文字キーボードショートカットを特定してフラグを立てる自動ルールはありません。その理由はアーキテクチャ上のものです。キーボードショートカットの挙動は JavaScript のイベントリスナー(
keydown、keyup、keypress)で実装されており、静的な DOM 解析では、特定のキーストロークがどのようなアクションをトリガーするのか、そのアクションがグローバルなのかフォーカスに限定されているのか、あるいはユーザー向けの無効化/再割り当ての仕組みが存在するのかを判断できません。ツールは、考え得るすべての文字入力についてキーストロークをシミュレートし、その結果としてのアプリケーションの状態変化を観察する必要がありますが、これは組み合わせ的に膨大でコンテキスト依存のタスクであり、現在の自動テストの能力を超えています。 - イベントリスナーの検査(部分的な自動化): ブラウザの DevTools は、
document、window、body要素に付与されたイベントリスナーを列挙できます。サイトがdocumentにkeydownリスナーを付与しており、そのソースを確認すると単一文字のマッチングロジックが見つかる場合、これは手動検証が必要な強いシグナルです。ただし、ツール単体では、その挙動がショートカットに該当するかどうか、また無効化の仕組みが存在するかどうかを判断できません。 - フレームワーク固有のショートカットライブラリ: 多くの React、Vue、Angular アプリケーションは、
react-hotkeys-hook、tinykeys、Mousetrapなどのライブラリを使ってグローバルショートカットを登録しています。手動監査では、ページソースやネットワークタブでこれらの依存関係を確認し、それから各登録ショートカットがこの達成基準の要件を満たしているかどうかをテストする必要があります。
テスト方法
- 既知の単一文字ショートカットについてアプリケーションを確認する: 利用可能なドキュメント、ヘルプページ、キーボードショートカットのリファレンスダイアログ(多くの場合 ? で開くか、ヘルプメニューからアクセス)を読みます。修飾キーなしで単一文字を使用していると記載されているショートカットをすべてリストアップします。
- JavaScript のイベントリスナーを検査する: Chrome DevTools または Firefox DevTools を開き、Elements パネルまたは Sources パネルに移動し、Event Listeners タブを使って
document、window、body上のリスナーを確認します。keydown、keyup、keypressハンドラーを探します。ハンドラーのソースを展開して読み、修飾キーのチェックなしに単一文字キーをテストしていないか(つまり、event.ctrlKey || event.metaKey || event.altKeyを確認せずにevent.key === 'n'をチェックしていないか)を確認します。 - テキスト入力にフォーカスがある状態でキーボードショートカットをテストする: テキストフィールド、検索ボックス、textarea をクリックしてフォーカスを当てます。そのうえで、特定した単一文字ショートカットを1つずつ押します。ショートカットが発火する(ナビゲーションが起こる、アクションがトリガーされる、状態が変化する)場合、それは不適合です — ショートカットがフォーカスに限定されておらず、ユーザーが入力中でも有効になっていることを意味します。
- NVDA + Firefox でテストする: NVDA のブラウズモードを有効にします(Insert+Space で切り替え)。ブラウズモードでは、NVDA は単一文字のナビゲーションキー(見出し用の H、ボタン用の B など)を使用します。テスト対象のウェブアプリケーションを起動します。フォーカスモード(Insert+Space)に切り替え、テキストを口述または入力します。ページ独自の単一文字ショートカットが NVDA のブラウズモードのキー操作と競合せず、意図しないアクションが発生しないことを確認します。
- JAWS + Chrome でテストする: 同様に、JAWS も単一文字のクイックナビゲーションを使用します。アプリケーションを起動し、JAWS の仮想カーソルでナビゲートし、JAWS がキーストロークを処理している間にアプリケーションのショートカットが予期せず発火しないことを確認します。
- VoiceOver + Safari(macOS)でテストする: VoiceOver を有効にします(Cmd+F5)。VO+Shift+下矢印でコンテンツ領域とインタラクトします。ページ上の文字キーショートカットが、VoiceOver のナビゲーションコマンドを妨げないことを確認します。
- 音声入力をシミュレートする: Dragon NaturallySpeaking や Windows 音声認識が利用可能な場合、アプリケーションを開いた状態でフォームフィールドにテキストを口述します。ショートカットに使われている文字で始まる一般的な単語やフレーズを話し、意図しないアクションがトリガーされないことを確認します。
- 無効化または再割り当ての仕組みを検証する: 単一文字ショートカットが存在する場合、それらをオフにしたり再割り当てしたりできる設定・環境設定のUIを探します。キーボードだけで到達でき、正しく機能することを確認します。ショートカットを無効化した後、その文字を押してもアクションが発生しないことをテストします。
修正方法
グローバルな単一文字ショートカットで修飾キーのチェックがない — 不適切な例
<!-- JavaScript が document に付与され、任意の 'n' キー押下でグローバルに発火する -->
<script>
document.addEventListener('keydown', function(event) {
if (event.key === 'n') {
// 新規メッセージ作成画面に遷移
openComposeWindow();
}
});
</script>
グローバルな単一文字ショートカット — 修正例: 修飾キーの必須化と無効化トグルの追加
<!-- 修正アプローチ1: Ctrl+N を必須にして誤発火を防ぐ -->
<script>
document.addEventListener('keydown', function(event) {
// Ctrl または Meta(Mac の Cmd)が押されている場合のみ発火
if ((event.ctrlKey || event.metaKey) && event.key === 'n') {
openComposeWindow();
}
});
</script>
<!-- 修正アプローチ2: 単一文字ショートカットが必要な場合は無効化トグルを提供する -->
<button type='button' id='toggle-shortcuts' aria-pressed='true'>
Keyboard shortcuts enabled
</button>
<script>
let shortcutsEnabled = true;
document.getElementById('toggle-shortcuts').addEventListener('click', function() {
shortcutsEnabled = !shortcutsEnabled;
this.setAttribute('aria-pressed', shortcutsEnabled.toString());
this.textContent = shortcutsEnabled ? 'Keyboard shortcuts enabled' : 'Keyboard shortcuts disabled';
});
document.addEventListener('keydown', function(event) {
if (!shortcutsEnabled) return; // ユーザーの設定を尊重
if (event.key === 'n') {
openComposeWindow();
}
});
</script>
フォーカスされたウィジェット内でアクティブなショートカット — 不適切な例
<!-- ショートカットがウィジェットではなく document 全体を監視している -->
<div id='autocomplete-list' role='listbox'>
<div role='option'>Istanbul</div>
<div role='option'>Ankara</div>
</div>
<script>
// バグ: document に付与されており、オートコンプリートにフォーカスがないときも発火する
document.addEventListener('keydown', function(e) {
if (e.key === 'Enter') selectHighlightedOption();
});
</script>
フォーカスされたウィジェット内でアクティブなショートカット — 修正例: リスナーをウィジェットにスコープする
<!-- 修正: リスナーをウィジェット要素に付与し、その要素にフォーカスがあるときだけショートカットが発火する -->
<div id='autocomplete-list' role='listbox' tabindex='0'>
<div role='option'>Istanbul</div>
<div role='option'>Ankara</div>
</div>
<script>
var widget = document.getElementById('autocomplete-list');
// リスナーはウィジェット自身に付与: Enter は listbox にフォーカスがあるときだけ発火
widget.addEventListener('keydown', function(e) {
if (e.key === 'Enter') selectHighlightedOption();
});
</script>
ユーザーがアクセス可能な再割り当て UI がない — 不適切な例
<!-- アプリケーションはライブラリでショートカットを登録しているが、設定ページを提供していない -->
<!-- ユーザーは 'g'(ギャラリーへ)や 'c'(カートへ)を変更・無効化する手段がない -->
<script src='hotkeys.min.js'></script>
<script>
hotkeys('g', function() { goToGallery(); });
hotkeys('c', function() { goToCart(); });
</script>
ユーザーがアクセス可能な再割り当て UI がない — 修正例: アクセシブルな設定パネルを追加
<!-- キーボードでアクセス可能な設定パネル。ユーザーがすべての単一文字ショートカットをトグルできる -->
<nav aria-label='Accessibility settings'>
<button type='button' id='open-shortcut-settings'>Keyboard shortcut settings</button>
</nav>
<dialog id='shortcut-settings-dialog' aria-labelledby='dialog-title'>
<h2 id='dialog-title'>Keyboard Shortcuts</h2>
<label>
<input type='checkbox' id='enable-single-char' checked />
Enable single-character keyboard shortcuts (G, C, N...)
</label>
<p>Disable this if you use speech recognition software or experience accidental activations.</p>
<button type='button' id='close-dialog'>Save and close</button>
</dialog>
<script src='hotkeys.min.js'></script>
<script>
var checkbox = document.getElementById('enable-single-char');
function applyShortcuts() {
if (checkbox.checked) {
hotkeys('g', function() { goToGallery(); });
hotkeys('c', function() { goToCart(); });
} else {
hotkeys.unbind('g');
hotkeys.unbind('c');
}
}
applyShortcuts();
checkbox.addEventListener('change', applyShortcuts);
document.getElementById('open-shortcut-settings').addEventListener('click', function() {
document.getElementById('shortcut-settings-dialog').showModal();
});
document.getElementById('close-dialog').addEventListener('click', function() {
document.getElementById('shortcut-settings-dialog').close();
});
</script>
よくある間違い
documentやwindowにショートカットを登録し、現在入力要素にフォーカスがあるかどうかを確認していない: 無効化の仕組みが存在する場合でも、多くの実装ではdocument.activeElementを確認し、ユーザーが<input>、<textarea>、contenteditable要素内にいるときにはショートカットを抑制する、という処理を忘れています。その結果、通常の入力操作と干渉してしまいます。?ショートカット(ヘルプを開く)を例外扱いする: クエスチョンマークは印字可能な文字であり、単一文字ショートカットです。フォーカスに限定されているか、無効化/再割り当ての仕組みが存在しない限り、この達成基準の例外にはなりません。- テキスト入力ではショートカットを無効化しているが、
contenteditable領域やリッチテキストエディタでは無効化していない: 音声入力ユーザーは、CMS プラットフォームのエディタなど、リッチテキストエディタで使用されるcontenteditable要素に対して口述することがよくあります。これらのコンテキストでグローバルショートカットを抑制しないのは、この達成基準の違反のままです。 - ユーザーのショートカット設定をセッションメモリにしか保存していない: ユーザーがショートカットを無効化した後にページをリロードした場合、その設定は(
localStorageやユーザープロファイル設定などに)永続化されているべきであり、訪問のたびにショートカットを無効化し直さなくて済むようにする必要があります。 - ショートカット設定の UI 自体がアクセシブルでない: 無効化/再割り当てオプションを、キーボードで到達できない深いメニュー階層に置いたり、
role='switch'やaria-checkedを適切に持たないカスタムトグルウィジェットを使用したりすると、修正の仕組みが、本来支援すべきユーザーにとって利用不可能になります。 - 文字キーだけが問題だと考えている: 数字キー(1–9)、句読点キー(/、.、カンマ、セミコロン)、記号キー(#、@、!)はすべて印字可能な文字です。これらを使った単一キーショートカットも、この達成基準の対象になります。
- どのショートカットが存在するかを文書化していない: 無効化の仕組みがあっても、どのショートカットが有効なのかユーザーが把握できなければ、効果的に利用することはできません。ヘルプボタンから開くダイアログなど、見やすくキーボードでアクセス可能なショートカットリファレンスを提供することが強く推奨されます。
- ショートカットライブラリのデフォルト設定がグローバルバインドであることを理解せずに使用している: Mousetrap、Hotkeys.js、tinykeys などのライブラリは、デフォルトでグローバルスコープにバインドします。開発者は、スコープの制限や修飾キーの必須化に関するドキュメントを読まずにこれらを使用してしまい、その結果、この達成基準に違反する実装を大規模に生み出してしまうことがあります。
- リリース前に音声認識でテストしていない: QA ツールキットに Dragon NaturallySpeaking を含めていないチームは、デプロイ後に音声入力ユーザーから問題が報告されるまで、単一文字ショートカットの競合に気づかないことがよくあります。
- ショートカットが「任意」または「パワーユーザー向け」だからといって例外だと考えている: この達成基準は、単一文字ショートカットすべてに適用されます。それが高度な機能として提供されているかどうかは関係ありません。機能が任意であることは、適合要件からの免除にはなりません。
トルコのアクセシビリティ規制との関係
トルコの大統領通達 2025/10は、2025年6月21日付官報第 32933 号で公布され、WCAG 2.2 に整合したウェブおよびモバイルのアクセシビリティ要件を義務付けています。WCAG 2.1.4「文字キーのショートカット」はレベルAの達成基準であり、この通達における最優先義務の階層に位置づけられます。
この通達は、トルコで事業を行う幅広い主体を対象としています。公共機関 — 省庁、自治体、国立大学、公立病院、政府機関など — は、通達の公布日から1年以内にレベルAの完全な適合を達成しなければなりません。対象となる民間部門の事業者には、2年の適合猶予期間が与えられています。対象となる民間事業者には、ECプラットフォーム、銀行・金融機関、病院・医療提供者、20万件以上の加入者を持つ通信会社、旅行代理店、民間輸送会社、国民教育省(MoNE)の認可を受けて運営される私立学校などが含まれます。
これらの組織にとって、WCAG 2.1.4 に適合しないことは、単なるベストプラクティスの問題ではなく、法的義務の問題です。単一文字の商品の閲覧ショートカットを無効化の仕組みなしに実装しているトルコのECサイトや、取引フローで文字キーショートカットを使用しているトルコの銀行のオンラインポータルは、この通達の要件に直接違反していることになります。
実務的には、対象組織のコンプライアンスチームは、WCAG 2.2 レベルAの是正プロジェクトの一環として、グローバルに登録された単一文字ショートカットを探すことを個別のタスクとして、自社の JavaScript コードベースおよびサードパーティのウィジェットライブラリを監査すべきです。この達成基準には手動テストが必要なため、自動アクセシビリティスキャンだけでは違反を検出できません — キーボードおよび音声入力に特化したテストを別途実施する必要があります。コンテンツ管理システムやフロントエンドフレームワークを使用している組織は、カスタムアプリケーションコードに加えて、プラットフォームレベルのショートカット実装(たとえば、CMS 管理画面のデフォルトキーボードショートカットが顧客向けページに露出していないか)も確認する必要があります。
Accsible のオーバーレイ SDK は、ユーザーがアクセス可能なアクセシビリティ設定パネルを提供し、エンドユーザーにショートカット無効化トグルを提示できるようにすることで、対象組織が WCAG 2.1.4 の「オフにする仕組み」の要件を、コードベース全体のリファクタリングなしに満たすことを支援します。これは、基盤となる JavaScript のショートカットロジックを変更することがリソース集約的であるレガシーアプリケーションを管理している組織にとって特に有用です。ただし、組織は、適合のためにオーバーレイだけに依存することは、基盤となるショートカット実装への対処の代替にはならないことに留意すべきです。オーバーレイツールとソースコードの是正を組み合わせた多層的なアプローチこそが、大統領通達の下で最も堅牢な適合への道筋となります。
出典と参考資料
- W3C Understanding 2.1.4 Character Key Shortcuts
- W3C Techniques for 2.1.4
- WebAIM: Keyboard Accessibility
- Deque University: WCAG 2.1.4 Character Key Shortcuts
- MDN: KeyboardEvent.key
- MDN: EventTarget.addEventListener
- W3C Technique G217: Providing a mechanism to allow users to remap or turn off character key shortcuts
