# キーボードでスクロールできないスクロール領域

Source: https://easeweb.dev/learn/scrollable-regions
Topics: キーボードとフォーカス > スクロールする領域をキーボードでスクロールできる (WCAG 2.1.1)
The fix: 決まった高さを外して規約をページと一緒に流すか、枠にtabindex="0"、role="region"、見出しからの名前と、見えるフォーカスリングを付けてTabの止まる場所にします。枠をフォーカスできるようにするのをブラウザーに任せてはいけません。ChromeとFirefoxはそうしますが、Safariはしません。
Test with: keyboard, zoom, screen reader
References: https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html https://www.w3.org/WAI/standards-guidelines/act/rules/0ssw9k/ https://dequeuniversity.com/rules/axe/4.13/scrollable-region-focusable https://developer.chrome.com/blog/keyboard-focusable-scrollers https://bugs.webkit.org/show_bug.cgi?id=190870 https://github.com/w3c/wcag/issues/3029 https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/region_role https://adrianroselli.com/2022/06/keyboard-only-scrolling-areas.html

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

ショップの購入手続きの最後に、「利用規約」という見出しの下の枠に規約があり、その下に「利用規約を読み、同意します」というチェックボックスと「注文を確定」ボタンがあります。規約は6つの条項があるため、枠は決まった高さにしてスクロールするようになっています。購入手続きが短く見え、マウス、トラックパッド、指を使う人なら、枠をスクロールして続きを読めます。

MacのSafariでキーボードを使う人が、メールアドレスの欄からTabを押すと、チェックボックスに移ります。枠は飛ばされました。矢印キーやPage Downを押すとページがスクロールし、枠は画面の上へ動きますが、枠の中の文章は動かないため、返品と返金の条項は見えないままです。チェックボックスに印を付けるには、読めなかった規約に同意するしかありません。

## 確認できる問題

達成基準2.1.1は、すべての機能をキーボードで操作できることを求めています。枠の中の隠れた文章を表示する方法は、枠をスクロールすることだけです。そしてキーボードで枠をスクロールできるのは、フォーカスが枠そのものか、枠の中にあるときだけです。この枠には `tabindex` がなく、中は段落だけなので、Tabが止まる場所がありません。

ブラウザーはこれを補い始めています。Firefoxは以前から、スクロールする枠にTabで止まります。ChromeとEdgeも、バージョン132から、中にフォーカスできるものがない枠に止まるようになりました。Safariはまだ止まりません。それを求めるWebKitのバグは2018年から未解決のままで、キーボードを付けたiPadでは、Chromeなどのブラウザーも、通常はSafariと同じエンジンで動きます。あるブラウザーではスクロールでき、別のブラウザーではできない枠は、別のブラウザーを使う人にとって、やはり基準を満たしません。

## 利用者への影響

SafariはすべてのMacとiPadに最初から入っているブラウザーなので、それらでキーボードを使う人の多くが開いているブラウザーです。タッチ操作が難しいため、iPadにキーボードを付けている人も含まれます。画面が小さくなるほど問題は広がります。ノートパソコンでは中身が収まる枠、たとえばスクロールする枠で囲んだ広い表は、スマートフォンや400%の拡大表示で初めてスクロールし始めることがよくあります。

## 自動チェックとAIの限界

axeの `scrollable-region-focusable` は、スクロールするのに、枠にも中にもTabの止まる場所がない枠を見つけます。EaseWebの診断は、これをほかのレベルAのルールと一緒に実行します。このルールの説明は、今は問題のあるブラウザーとしてSafariを挙げています。axeはページを読み込んだときの大きさで調べるため、狭い画面でだけスクロールする枠は見えません。診断のリフローの確認は、ページを幅320ピクセルにして、そうした枠を `ew:reflow-scroller-not-focusable` として報告します。どちらも、枠の中にリンク、ボタン、入力欄が一つでもあれば十分とみなします。矢印キーを自分で使ってしまう入力欄でも同じです。Chromeで手動でテストしても何も見つかりません。Chromeは枠に自分で止まるためです。AIによる修正は、名前もフォーカスリングもない `tabindex="0"` だけを付けることや、`overflow: hidden` でスクロールバーを消すことがあります。後者では、条項は誰にとっても見えないままになります。

## 修正前：中にフォーカスできるもののないスクロールの枠

```html
<form action="/checkout" method="post">
  …
  <h2 id="terms-heading">利用規約</h2>
  <div class="terms">
    <p><strong>1. ご注文</strong> ご注文は、確認のメールをお送りした時点で承ります。</p>
    …
    <p><strong>5. 返品</strong> 未使用の商品は、お届けから30日以内に返品できます。</p>
    <p><strong>6. 返金</strong> 返品の到着から5営業日以内に、お支払いに使われたカードへ返金します。</p>
  </div>
  <label>
    <input type="checkbox" name="accept-terms" required>
    利用規約を読み、同意します
  </label>
  <button type="submit">注文を確定</button>
</form>
```

```css
.terms {
  max-height: 10rem;
  overflow-y: auto;
  padding: 0.75rem 1rem;
  border: 1px solid #8a8a8a;
  border-radius: 8px;
}
```

枠は高さ10remでスクロールしますが、中にフォーカスできるものがなく、枠そのものもTabの止まる場所ではありません。Safariでは、Tabは枠の前の欄から後ろのチェックボックスへ移り、どのキーでも枠の中の文章は動きません。

## 修正後：Tabで届き、名前の付いたスクロールの枠

```html
<form action="/checkout" method="post">
  …
  <h2 id="terms-heading">利用規約</h2>
  <div class="terms" tabindex="0" role="region" aria-labelledby="terms-heading">
    <p><strong>1. ご注文</strong> ご注文は、確認のメールをお送りした時点で承ります。</p>
    …
    <p><strong>5. 返品</strong> 未使用の商品は、お届けから30日以内に返品できます。</p>
    <p><strong>6. 返金</strong> 返品の到着から5営業日以内に、お支払いに使われたカードへ返金します。</p>
  </div>
  <label>
    <input type="checkbox" name="accept-terms" required>
    利用規約を読み、同意します
  </label>
  <button type="submit">注文を確定</button>
</form>
```

```css
.terms {
  max-height: 10rem;
  overflow-y: auto;
  padding: 0.75rem 1rem;
  border: 1px solid #8a8a8a;
  border-radius: 8px;
}
.terms:focus-visible {
  outline: 3px solid #1a4fd0;
  outline-offset: 2px;
}
```

`tabindex="0"` で、どのブラウザーでも枠がTabの順序に入ります。前の欄とチェックボックスの間です。フォーカスが移れば、矢印キー、Page Up、Page Down、Home、End、Spaceで枠がスクロールします。枠にはほかにフォーカスを示す見た目がないため、リングでフォーカスの位置を示します。`role="region"` と `aria-labelledby` があると、Tabで移ったときにスクリーンリーダーが「利用規約、領域」と読み上げ、何の前置きもなく最初の条項から読み始めることがなくなります。役割と名前はWCAGの要件ではありません。ワーキンググループは2026年10月に、一般的な役割だけを持つフォーカスできる要素は4.1.2を満たさないことにはならない、と合意しました。役割と名前は、ページを耳で聞く人のために付けます。

## 修正後：ページと一緒に流れる規約

```html
<form action="/checkout" method="post">
  …
  <h2 id="terms-heading">利用規約</h2>
  <div class="terms">
    <p><strong>1. ご注文</strong> ご注文は、確認のメールをお送りした時点で承ります。</p>
    …
    <p><strong>5. 返品</strong> 未使用の商品は、お届けから30日以内に返品できます。</p>
    <p><strong>6. 返金</strong> 返品の到着から5営業日以内に、お支払いに使われたカードへ返金します。</p>
  </div>
  <label>
    <input type="checkbox" name="accept-terms" required>
    利用規約を読み、同意します
  </label>
  <button type="submit">注文を確定</button>
</form>
```

```css
.terms {
  padding: 0.75rem 1rem;
  border: 1px solid #8a8a8a;
  border-radius: 8px;
}
```

決まった高さを外すと、枠は文章の高さになり、代わりにページがスクロールします。ページのスクロールは、どのブラウザーでもキーボードでできます。矢印キー、Page Down、Spaceのほか、Tabでも、最後の条項の下にあるチェックボックスが表示されます。Tabの順序に加わるものはなく、名前を付けるものもありません。ページは規約の高さの分だけ長くなります。購入手続きには長すぎる場合は、配送、返品、返金のように、この段階で購入する人に必要な条項だけを残し、全文は別のページにして、チェックボックスの上にリンクを置きます。

## どの方法を選ぶか

どちらも、どのブラウザーでも2.1.1を満たします。規約をページと一緒に流すほうが変更は小さく、Tabの止まる場所も増えず、スクリーンリーダーのために名前を付けるものもありません。代わりにページが長くなるため、その場で読める長さの文章か、要約とリンクにまとめられるときに選びます。Tabの止まる場所にする方法は、デザインどおりのコンパクトな枠を残せるので、長い使用許諾契約や増え続けるログのように、枠に入れておく必要のある内容に向いています。代わりに、Tabの止まる場所が一つ増え、名前を正しく保ち、フォーカスリングをデザインする必要があります。

## 実装の判断

同じ問題はほかの枠にも現れ、それぞれに直し方があります。

- `overflow-x: auto` の枠で囲んだ広い表：[狭い画面で横スクロールが出るページ](/ja/learn/reflow)にあるように、枠に `tabindex="0"` と `role="region"` を付け、表の `caption` から名前を付けます。スマートフォンでだけスクロールすることが多いため、そこで確認します。
- 横にスクロールする `pre` のコード例：`pre` に `tabindex="0"` を付けるか、改行しても意味が変わらない場所では長い行を折り返します。
- 高さの決まったレビューや更新履歴の欄：ページと一緒に伸びるようにし、続きはボタンで読み込むか、欄をTabの止まる場所にします。

枠の中のリンク、ボタン、入力欄は、axeとW3CのACTルールが、枠そのもののTabの止まる場所の代わりとして認めるものです。Chromeでは、リンクやボタンから矢印キーを押すと、それを含む枠がスクロールします。入力欄、セレクト、ラジオボタンのグループは矢印キーを自分で使うため、フォーカスできるものがそれだけの枠は、やはり矢印キーでスクロールできません。枠そのものに `tabindex="0"` を付けます。

スクロールする枠には、`tabindex="-1"` を付けてはいけません。どのブラウザーでも枠がTabの順序から外れ、本来なら止まるブラウザーでも止まらなくなります。

スマートフォンでだけスクロールする枠に `tabindex="0"` を付けると、スクロールしないノートパソコンでもTabの止まる場所が一つ増えます。1回多く押すだけで基準を満たさないわけではありませんが、スクロールするかもしれないという理由で、すべての枠に `tabindex` を付けてはいけません。名前の付いた領域はランドマークになるため、[区別できない複数のナビゲーションランドマーク](/ja/learn/landmark-names)でランドマークの名前について説明しているとおり、本当に必要な少数の枠にとどめます。リングは枠そのものに、オフセットを付けて描き、枠の枠線や `overflow` で切れないようにします。リングの色と強制配色については、[フォーカス表示が見えない独自デザインのボタン](/ja/learn/visible-focus)で扱っています。

## 修正の確認

1. MacのSafariで、詳細設定の「Tabキーを押したときにウェブページ上の各項目を強調表示」をオンにし、マウスを使わずにメールアドレスの欄からTabを押す。チェックボックスの前に、規約の枠に見えるリングが付いてフォーカスが止まること。または枠がなく、規約がページの一部になっていること。
2. 枠にフォーカスがある状態で、枠がなければページで、矢印キー、Page Down、Spaceを使い、最後の条項「6. 返金」を表示する。続けてTabでチェックボックスと「注文を確定」へ進めること。
3. 幅320ピクセルのウィンドウ、または幅1280ピクセルのウィンドウで400%の拡大表示にして、手順1と2を繰り返す。ページの残りもTabで進み、Tabの止まる場所のないままスクロールする枠がほかにないことを確認する。
4. VoiceOverかNVDAで規約へTabで移る。「利用規約、領域」のように枠の名前と役割が読み上げられるか、見出しと条項がページの残りと一緒に順に読み上げられること。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通の購入手続き、表、コードのコンポーネントを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。ここで扱うのは、ブラウザー自身のスクロールでスクロールする枠です。矢印のボタンでスクロールするカルーセルやリストは[キーボードやスクリーンリーダーで使えないカルーセル](/ja/learn/carousels)で、文字を拡大すると `overflow: hidden` で文章が切れ、まったくスクロールできない枠は[拡大した文字が切れる、高さ固定のボックス](/ja/learn/resize-text)で扱っています。Chromeだけでなく、Safariでも、利用者が使う画面幅で、操作全体を確認してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
