Claude Media
Claude Codeでキーボード操作できない画面を洗い出し、フォーカス順を直す

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の役割は、疑わしい箇所の列挙と、記録の整理、修正差分の作成です。順序が「意味を保っているか」の最終判断は、画面の目的を知っている人が下すほうが確実です。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/chrome
  2. developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/tabindex
  3. developer.mozilla.org/ja/docs/Web/CSS/:focus-visible
  4. w3.org/WAI/WCAG22/Understanding/focus-order.html
  5. w3.org/WAI/WCAG22/Understanding/no-keyboard-trap.html
  6. w3.org/WAI/WCAG22/Understanding/bypass-blocks.html
  7. w3.org/WAI/WCAG22/Understanding/focus-visible.html
  8. w3.org/WAI/WCAG22/Understanding/keyboard.html
  9. w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html
この記事を共有:XはてブLinkedIn