操作可能 / 2.4 ナビゲーション可能

2.4.11隠されないフォーカス(最低限)

レベル AA2.2 新規

Focus Not Obscured (Minimum)

キーボードでフォーカスした要素が、固定ヘッダーやダイアログなどに完全に隠れて見えなくならないようにする。

WCAG 2.2 で新しく追加された達成基準です

この基準は WCAG 2.1 にはなく、2.2 で新設されました。 まだ日本語の解説が少ない領域なので、下記のリンク先とあわせて理解を深めてください。

なぜ「隠れないフォーカス」が必要なの?

ウェブサイトでよく見かける「上部に固定されたナビゲーションバー」は、 スクロールしても常に画面上部に残る便利な仕組みです。 ところが、キーボードで操作するユーザーには深刻な問題を引き起こすことがあります。

キーボードの Tab でリンクやボタンにフォーカスを移すと、 ブラウザは対象の要素が見える位置まで自動スクロールします。 しかし固定ヘッダーの高さ分だけ「視覚的に隠れた領域」があることを ブラウザは自動では考慮しません。その結果、フォーカスされた要素がヘッダーの真裏に完全に潜り込んで見えなくなることがあります。

「今どこにフォーカスがあるのか」が分からなくなると、 マウスを使えないユーザーは操作を続けることができません。 これを防ぐのが達成基準 2.4.11 の目的です。

補足

達成基準 2.4.11(AA)は「フォーカスされた要素が固定要素に完全に隠れない」ことを求めます。 一部でも見えていれば最低限の要件は満たします。 AAA の 2.4.12 はさらに厳しく「まったく隠れない」を求めます。 まずは AA の「完全に隠さない」から確認しましょう。

不合格の例(フォーカスが隠れる)

下のデモは、スクロール領域の上部に position: sticky の不透明ヘッダーがある構成です。 コンテンツ側に scroll-margin-top が指定されていないため、 Tab でフォーカスが先頭の項目に移ると、ヘッダーの裏に完全に隠れてしまいます。

フォーカスが sticky ヘッダーに隠れる(不合格)

サイトの各セクションへ移動できます。Tab で項目を選んでください。

Tab キーでデモ内に入ってフォーカスを移してみましょう。先頭の「概要」ボタンにフォーカスが当たったとき、固定ヘッダーの裏に完全に隠れて見えなくなります。

合格の例(scroll-margin-top で隠さない)

まったく同じ構造に、ボタンへscroll-margin-top(固定ヘッダーの高さ分)を加えただけです。 フォーカスが当たると、ブラウザが自動的にヘッダーの下に収まる位置まで スクロールしてくれます。JavaScript は不要です。

scroll-margin-top でフォーカスを見える位置に保つ(合格)

サイトの各セクションへ移動できます。Tab で項目を選んでください。

同じようにTabで移動しても、「概要」ボタンは常に固定ヘッダーより下に見えています(scroll-margin-top の効果)。

直し方(コード)

良い例 / 推奨

scroll-margin-top をフォーカス可能な要素に指定するだけです。 値を CSS 変数で管理すると、ヘッダーの高さが変わったときに一か所直すだけで済みます。

/* 1. sticky ヘッダーの高さを CSS 変数で管理する */
:root {
  --header-height: 56px; /* sticky ヘッダーの実際の高さに合わせる */
}

/* 2. フォーカスを受け取りうる要素すべてに余白を付ける
      ヘッダー高さ + 少し余裕(8px)で確実にヘッダーの下に収まる */
.page-content a,
.page-content button,
.page-content input,
.page-content select,
.page-content textarea,
.page-content [tabindex] {
  scroll-margin-top: calc(var(--header-height) + 8px);
}

ポイント

scroll-margin-top はブラウザの対応も幅広く、JavaScript なしで完結します。 固定ヘッダーだけでなく、固定フッターや Cookie バナーが下部に固定されている場合はscroll-margin-bottom も同様に設定しましょう。 値はヘッダー高さより少し多め(+8px 程度)にすると視覚的に余裕が生まれます。

悪い例 / 避ける

この問題が起きる主な原因:

  • 不透明な sticky / fixed ヘッダーを置いただけで、 コンテンツ側への補正がない
  • scroll-margin-top が未指定 — ブラウザは「要素がスクロール領域内に入った」と判断するが、 固定要素で視覚的に隠れていることには気づかない
  • Cookie バナー・チャットウィジェット・固定フッターなど後から追加される固定要素でも同様に発生する
  • キーボード利用者は「今どこにいるか」が分からず、 操作を継続できなくなる
/* ❌ sticky ヘッダーが不透明なのに、コンテンツ側に補正がない */
.site-header {
  position: sticky;
  top: 0;
  height: 56px;
  background: #ffffff; /* 不透明な背景でコンテンツを覆う */
  z-index: 100;
}

/* コンテンツ要素に scroll-margin-top の指定なし          */
/* → Tab でフォーカスした要素がヘッダーの裏に完全に隠れる */

チェックリスト

  • ページに position: sticky / position: fixed の ヘッダー・フッターがある場合、フォーカス可能な要素にscroll-margin-top(または scroll-margin-bottom)を付けている
  • Tab キーでフォーカスを移し、フォーカスされた要素が 固定要素に完全に隠れないことを実機確認している
  • Cookie バナー・サポートチャット・トースト通知など、 後から表示される固定要素でも同様に確認している
  • scroll-margin-top の値はヘッダー高さと連動しており、 CSS 変数などでデザイン変更に追従できる仕組みがある
  • フォーカスリングを消していない(outline: none を使っていない)

原典・規範文書