Claude Codeでキーボード操作できない画面を洗い出し、フォーカス順を直す
Tabキーだけで画面を辿れるかを、Claude Codeにソース検索とブラウザ操作の2段で調べさせる手順です。フォーカス順の乱れ、トラップ、skip link、フォーカス表示の直し方までをコード付きで示します。
マウスを使わずTabキーだけで画面を最後まで辿れるかは、自動検査ツールが拾いにくい領域です。Claude Codeは、ソースの検索とブラウザ操作の両方ができるので、この確認を「疑わしい箇所の洗い出し」「実際にTabを辿った記録」「修正と再確認」の3段に分けて任せられます。
ここでは、操作できない要素、フォーカス順の乱れ、フォーカストラップ、skip linkの欠落、フォーカス表示の消失と、固定ヘッダーへの隠れに絞ります。WCAG全般の監査はaccessibility-reviewスキルの解説に、ツールによる自動検査はAxe Accessibilityプラグインの解説にあります。
何をもって「キーボードで操作できない」とみなすか
判定の物差しを先に決めておくと、Claudeへの指示がぶれません。WCAG 2.2の解説ページに載る6つの達成基準が、そのまま6つの症状に対応します。
| 症状 | 達成基準 | レベル |
|---|---|---|
| キーボードで操作できない要素がある | 達成基準2.1.1キーボード | レベルA |
| Tabの順番が見た目や意味とずれる | 達成基準2.4.3フォーカス順序 | レベルA |
| あるボタンにフォーカスが入ると抜け出せない | 達成基準2.1.2キーボードトラップなし | レベルA |
| 毎ページ繰り返すメニューを飛ばせない | 達成基準2.4.1ブロックスキップ | レベルA |
| いまどこにフォーカスがあるか見えない | 達成基準2.4.7フォーカスの可視化 | レベルAA |
| フォーカス中の要素が固定ヘッダーなどに隠れる | 達成基準2.4.11フォーカスが隠されない(最小) | レベルAA |
2.1.1は、すべての機能がキーボードインターフェースだけで操作できることを求めます。クリックにしか反応しない要素や、ホバーでしか開かないメニューは、この基準に当たります。2.4.11はWCAG 2.2で加わった基準で、フォーカスを受けた要素が、サイト側が置いた固定ヘッダー・バナー・チャット窓などに完全には隠れないことを求めます。
2.4.3は、順次ナビゲーションの順序が意味や操作性に影響するとき、フォーカス可能な要素が「意味と操作性を保つ順序」で受け取ることを求めます。2.1.2は、キーボードでフォーカスを入れられるなら、キーボードだけで外へ出せることが条件です。Tabや矢印キー以外の操作が要るときは、その方法を利用者に知らせます。
2.4.1の解説では、ページ先頭に本文へ直接飛ぶリンクを置く手法が、達成方法の1つとして挙げられています。2.4.7は、キーボード操作に対してフォーカス表示が見える動作モードを求める基準です。
この表をそのままClaudeに渡し、「各症状で何件、どのファイルか」を報告させるのが出発点になります。
手順1: ソースから疑わしい箇所を先に洗い出す
ブラウザを動かす前に、ソースの検索だけでかなり絞れます。トークンも時間も安く済むので、先にやる価値があります。次の4つの検索パターンを、プロジェクトの規模に合わせて渡します。
# 1. フォーカス表示を消している箇所
rg -n "outline:\s*(none|0)" src --glob "*.{css,scss,tsx,vue}"
# 2. 1以上のtabindex(順序の上書き)
rg -n "tabindex=[\"{']?[1-9]" src
# 3. クリックできるのにボタンでもリンクでもない要素
rg -n "<(div|span)[^>]*onClick" src
# 4. 見た目の順序だけを入れ替えるCSS
rg -n "flex-direction:\s*(row|column)-reverse|\border:\s*-?[0-9]" src --glob "*.{css,scss}"それぞれが何を疑う根拠になるかは、MDNの tabindex と :focus-visible のページにあります。
- 検索1の
outline: noneは、代わりの表示がなければキーボード操作を見えなくします。MDNは、フォーカススタイルを除去すると視覚的に見えるユーザーにはキーボードナビゲーションが使えなくなる、と述べています(2.4.7)。 - 検索2の
tabindexに0より大きい値を付けると、その要素は通常の順序より先にフォーカスを受けます。値は0と-1だけにとどめます。正の値やフレックスアイテムのorderによる並べ替えは、キーボードや支援技術の利用者に使いにくくなります(2.4.3)。 - 検索3の
<div onClick>は、フォーカスを受けず、アクセシビリティツリーにもボタンとして載りません。<a>・<button>・<input>・<select>・<textarea>のような対話型要素に置き換えます(2.1.1)。
Claudeには、検索結果をそのまま貼らせず、次の形に整理させます。
上の4つの検索を実行し、ヒットごとに次の列の表で報告して。
ファイル:行 / 症状(順序・トラップ・可視化・操作不能) / 修正案の1行 / 誤検知の可能性
修正はまだしないこと。「誤検知の可能性」の列が重要です。たとえば outline: none の直後に :focus-visible の代替スタイルがあれば問題はありません。この列があると、直す対象と見送る対象を後から分けられます。
手順2: ブラウザでTabを辿らせて順序を記録する
静的な検索では、実際にフォーカスが動く順番まではわかりません。ここでClaude Codeのブラウザ連携を使います。連携は claude --chrome で起動するか、セッション内で /chrome を実行して設定します。利用には、Claude in Chrome拡張機能の1.0.36以降と、直接契約のAnthropicプラン(Pro・Max・Team・Enterprise)が要ります。APIキーでの認証では、Chrome連携はオフのままです。
claude --chrome調べる画面は1回に1つに絞ります。入力欄が多いフォーム、設定画面、モーダルを開く画面から始めると、症状が出やすくなります。起動後の指示は、観察して記録するだけにとどめます。直す作業を混ぜないほうが、記録が安定します。
localhost:3000/settings を開いて、キーボードだけで操作したときの
フォーカス順を調べて。Tabキーを押すたびに、フォーカスされた要素の
種類・ラベル・画面上の位置を番号付きで記録して。
次の4点が見つかったら、その番号を報告して。
- 画面の上から下、左から右の流れと逆行した箇所
- Tabを10回続けても同じ範囲から出られない箇所
- どこにフォーカスがあるか見た目で判別できない箇所
- フォーカスされた要素が固定ヘッダーやバナーに隠れている箇所ブラウザで使えるツールの一覧は、/mcp から claude-in-chrome を選び、View toolsで確認できます。キー入力に使えるツールの有無はここで確かめてください。ページの操作とコンソールの読み取りは、連携の機能として説明されています。
キー入力が難しいときの代替
キー操作のツールが使えない構成なら、コンソールの読み取りを使います。次のコードを開発中の画面に一時的に入れ、フォーカスが移るたびにログを出させます。連携の説明にあるとおり、Claudeはコンソールのメッセージを読めます。
// 開発用の一時コード(確認が済んだら削除)
document.addEventListener("focusin", (e) => {
const el = e.target;
const r = el.getBoundingClientRect();
const label = el.getAttribute("aria-label") || el.textContent.trim().slice(0, 20);
console.log("[focus]", el.tagName, label, Math.round(r.top), Math.round(r.left));
});あなたが画面でTabを何度か押し、Claudeにコンソールの [focus] の行を読ませます。位置の列が上下に飛んでいれば、順序の乱れの手がかりになります。
読み取りの指示は、パターンを絞って伝えます。連携の説明も、コンソールのログは長くなりやすいので、見たいパターンを伝えるよう勧めています。
ログインが要る画面の扱い
連携は、ブラウザのログイン状態を共有します。ログインページやCAPTCHAに当たると、Claudeは止まって手動の対応を求めます。管理画面を調べる場合は、先に自分でログインしておくと、記録が途中で止まりません。
手順3: 症状別に直す
記録と検索結果が揃ったら、修正を依頼します。症状ごとに直し方の型があるので、型を指定すると差分が小さく済みます。
クリック可能なdivをボタンに置き換える
<!-- 修正前: Tabで届かず、Enterも効かない -->
<div class="save" onclick="save()">保存</div>
<!-- 修正後: 標準で到達でき、Enter・Spaceでも動く -->
<button type="button" class="save" onclick="save()">保存</button>tabindex="0" を足す方法もありますが、本筋は <button> に置き換えることです。足すだけだと、Enterキーなどの操作を自前で実装することになります。
正のtabindexを外して、DOMの順序を直す
<!-- 修正前 -->
<input name="email" tabindex="2">
<input name="name" tabindex="1">
<!-- 修正後: 属性を外し、ソース上の並びを論理的な順にする -->
<input name="name">
<input name="email">ソース上の並びを論理的な順にするのが正攻法です。見た目だけを変えたいときは、CSSの order ではなくレイアウト側の並べ替えを見直します。
フォーカス表示を :focus-visible で取り戻す
/* 修正前 */
button { outline: none; }
/* 修正後: キーボード操作のときだけ、はっきりした輪郭を出す */
button:focus-visible {
outline: 3px solid #1a56db;
outline-offset: 2px;
}:focus-visible は、2022年3月以降すべてのブラウザーで使えます。マウスでクリックしたボタンに輪郭を出さず、キーボードでは出す、という、キーボード操作かどうかを見分けるブラウザーの判断に、そのまま従えます。色の選び方は、WCAG 2.1の1.4.11(非テキストのコントラスト)が関わり、フォーカス表示には3:1以上が求められます。
skip linkを足す
<body>
<a class="skip-link" href="#main">本文へ移動</a>
<header>…毎ページ共通のメニュー…</header>
<main id="main" tabindex="-1">…</main>
</body>.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 8px; top: 8px; background: #fff; padding: 8px; }リンクは画面外に置き、フォーカスを受けたときだけ見える位置に出します。先頭でTabを押した人が最初に当たる要素になります。main に tabindex="-1" を付けるのは、Tabの順番には加えず、移動先として確実にフォーカスを受けるためです。-1はこの用途に向いた値です。
モーダルの出入りを整える
トラップの典型は、モーダルが開いたのに背後の要素へフォーカスが漏れる、または逆に閉じられない場合です。自前のdivでモーダルを作っている場合は、HTMLの <dialog> 要素に置き換えられないかをClaudeに確認させます。置き換えられない場合は、開いたときに中の要素へフォーカスを移し、閉じたときに開いた元のボタンへ戻す処理が要ります。この2点は、手順2の記録で必ず確かめます。
MDNは <dialog> 要素に tabindex 属性を使ってはいけないとしています。tabindex="-1" を足して直そうとする修正は、ここで止めてください。
修正後に同じ手順で再確認する
直した後は、手順2と同じ指示を同じ画面に再実行します。前回の記録を見せて「順序の逆行は何番から何番に変わったか」を比べさせると、直ったことを数で確かめられます。
さっきの記録(前回の表)と今回の記録を並べて、
逆行・トラップ・不可視の件数がそれぞれどう変わったか表にして。
減っていない項目は原因の仮説も1行添えて。繰り返し使うなら、CLAUDE.mdに規約を残します。
## キーボード操作の規約
- クリックできる要素は button か a を使う。div に onClick を付けない
- tabindex は 0 と -1 だけ。1 以上は使わない
- outline を消すときは同じコミットで :focus-visible の代替を足す
- UI を変えたら、変更した画面を Tab で最後まで辿って記録する見落としやすいつまずき
- 負のtabindexで外す:
tabindex="-1"を付けた要素は、Tab順から消えます。MDNは、既定でフォーカスできる要素に負の値を付けると、フォーカス順から外れると述べています。フォームのボタンに誤って付けると、キーボードでは到達できません。 <dialog>にtabindexを付ける: 前述のとおり、MDNが禁じる使い方です。- 自動検査の合格を完了とみなす: 検査ツールが緑でも、順序の意味はわかりません。2.4.3は「意味と操作性を保つ順序」を求めるので、最後は人が辿って確かめます。
- ホバーでしか出ないメニュー: マウスでは開くのにフォーカスでは開かない例で、2.1.1に当たります。検索パターンには引っかからないので、手順2の記録で「届かなかった要素」を拾います。
- 固定ヘッダーがフォーカスを隠す: Tabで下へ進むと、フォーカスされたリンクが画面上部の固定ヘッダーの裏に入り込むことがあります。2.4.11は、完全に隠れないことを求めます。手順2の4つ目の観察項目で拾います。
- 拡張機能が見えない: Chrome連携の接続まわりはClaude in Chromeが動かないときの切り分けにまとめています。
使い分けと、この手順の限界
この手順は、Tabキーで届くかどうかに絞っています。見出しの構造、色のコントラスト、スクリーンリーダーの読み上げは扱いません。それらはaccessibility-reviewスキルや、Axe Accessibilityプラグインのような検査の領分です。
画面の見た目を整える段階では、frontend-designプラグインで生成したUIにも、同じ検索パターンを当てられます。見た目を優先して outline: none を入れがちな箇所だからです。
キー操作を最も確実に確かめる方法は、結局あなた自身がTabを数十回押すことです。Claudeの役割は、疑わしい箇所の列挙と、記録の整理、修正差分の作成です。順序が「意味を保っているか」の最終判断は、画面の目的を知っている人が下すほうが確実です。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- code.claude.com/docs/en/chrome
- developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/tabindex
- developer.mozilla.org/ja/docs/Web/CSS/:focus-visible
- w3.org/WAI/WCAG22/Understanding/focus-order.html
- w3.org/WAI/WCAG22/Understanding/no-keyboard-trap.html
- w3.org/WAI/WCAG22/Understanding/bypass-blocks.html
- w3.org/WAI/WCAG22/Understanding/focus-visible.html
- w3.org/WAI/WCAG22/Understanding/keyboard.html
- w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html