シリーズ「アクセシビリティ通信」ではウェブアクセシビリティに関するトピックを取り上げていきます。今回は固定配置について取り上げます。

CSS の position: fixedposition: sticky により、コンテンツを固定配置にする手法はよく用いられます。

本記事では、position: fixedposition: sticky の両方を固定配置と呼びます。

この手法を使用することで、グローバルナビのように頻繁に使用する要素を常に表示することができたり、EC サイトで商品画像と商品情報を常に並べて表示するといったように、ユーザの利便性を向上することができます。

固定配置の CSS の例
header {
  position: fixed;
  top: 0;
}
.image {
  position: sticky;
  top: 0;
}

しかし、この固定配置する要素のサイズや点数、配置によっては、アクセシビリティが確保されないケースがあるので注意が必要です。

アクセシビリティ上の注意点

見出し「アクセシビリティ上の注意点」

WCAG 2.1 の「1.4.10 リフロー(レベル AA)」では、以下のような達成基準が定められています。

達成基準 1.4.10 リフロー (レベル AA): コンテンツは、情報又は機能を損なうことなく、かつ、以下において 2 次元スクロールを必要とせずに提示できる:

  • 320 CSS ピクセルに相当する幅の縦スクロールのコンテンツ
  • 256 CSS ピクセルに相当する高さの横スクロールのコンテンツ
達成基準 1.4.10: リフローを理解する | WCAG 2.1 解説書

この基準のおもな目的としては、ロービジョンのユーザがズーム機能を利用したときに、スクロールせずに拡大されたコンテンツを取得できるようにすることですが、適切にレスポンシブウェブデザインのテクニックを使用することで、アクセシビリティを確保することができます。

関連して、基準を達成するための必須条件ではないですが、参考達成方法として以下のページが用意されています。

ここでは、リフローの達成基準に関連して、ズーム機能を使用しているときや、スマートフォンを横持ち(landscape)にしているときなどに、スティッキー要素によって、コンテンツの取得を困難にしていないかが言及されています。

具体的な解決策としては以下のコードのように、ある一定の高さが確保されているときのみ、position: sticky を有効にします。

ビューポートの高さが 480px 以上のときにヘッダをスティッキー配置にする例
@media (height >= 480px) {
  header {
    position: sticky;
    top: 0;
  }
}

なお、この 480px の値は、あくまでも一例なので、配置する要素のサイズやページのレイアウトによって適宜調整する必要があります。

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

見出し「2.4.11 隠されないフォーカス(最低限)」

2023 年内に勧告予定の WCAG 2.2 では、「2.4.11 隠されないフォーカス(最低限)(レベル AA)」と「2.4.12 隠されないフォーカス(高度)(レベル AAA)」の達成基準が新たに追加される予定です1

2023/08/27 追記 WCAG 2.2 の W3C 勧告は 2023 年内の公開になるようです。

これらの基準では、ある要素がキーボードフォーカスを受け取ったときに、前者の場合は少なくとも要素の一部が見えており、後者の場合は完全に見えていることが求められます。

対象となる要素の例としては、以下が考えられます。

  • グローバルヘッダ・フッタ
  • 開閉するメニュー(ドロワーメニュー、ドロップダウンメニューなど)
  • ダイアログ要素
  • ウィジェット(チャットボット、カレンダーなど)
  • バナー(Cookie バナー、広告バナーなど)
  • そのほか、固定配置される要素(CTA、シェアボタンなど)

さきほど紹介した「1.4.10 リフロー」の参考達成方法でも、固定配置した要素とキーボード操作によるアクセシビリティ上の懸念点が言及されています。少し長いですがそのまま引用します。

注記

スティッキー領域は、キーボード利用者にとって不利になる可能性があるため、慎重に使用する必要があることに注意する。固定ヘッダーのあるページをタブで移動するキーボード利用者にとっての問題は、ページがスクロールを開始した後に、ページの上方にあるインタラクティブ要素に到達するために逆方向でタブ移動すると、多くの場合、フォーカスがスティッキーヘッダーの背後に移動した時点で見えなくなることである。そのため、利用者は、フォーカスを見るために上にスクロールしなければならないが、これは必ずしも意識して行っているわけではないだろう。同様に、目に見えるフォーカスはスティッキーフッターの後ろに消えてしまうので、利用者はフォーカスの位置を見るために下にスクロールする必要があり、これは非常に面倒である。

C34: 固定されていないスティッキーヘッダー/フッターに、メディアクエリーを利用する | WCAG 2.1 達成方法集

キーボード操作のみでフォーカス可能な要素の間を移動している際に、固定配置された要素が上に重なることで、フォーカスを見失うことが考えられます。

解決策としては、フォーカスを受ける要素に対して scroll-margin を指定して、固定配置の要素分のスペースを確保する方法が挙げられます。

また、メニュー要素やダイアログ要素などは、それらの要素を閉じるまではフォーカスの移動を要素内に制限させることで、この基準を満たすことができるかもしれません(フォーカストラップ)。

本サイトにおいては、固定配置は積極的には使用していませんが、おもにプロジェクトページ内において活用することがあります。

以下は「RECTBEATS(レクトビーツ)」というプロジェクトですが、プレビューエリアとその下のコントロールエリアを同時に見えるようにするために、ビューポートの条件に応じて固定配置(position: sticky)を使用しています。

「RECTBEATS」でスクロールダウンしたときの図
プレビューエリアが固定配置されているので、スクロールするとコントロールエリアに重なる

具体的には、以下の条件に一致するときにプレビューエリアを固定配置(position: sticky)にしています。

  • ビューポート幅が 640px 以下
  • ビューポートの高さが 640px 以上
  • ビューポートのアスペクト比が 2/3 以下
メディアクエリの条件に一致するときに固定配置を有効に
@media (width <= 640px) and (height >= 640px) and (aspect-ratio <= 2/3) {
  .preview-container {
    position: sticky;
    top: 0;
  }
}

このままでは、キーボード操作のみでフォーカス間を移動すると、固定配置のプレビューエリアの下に要素が隠れしまうことがあるので、アプリの子要素すべてに scroll-margin を指定してスペースを確保します。

子要素に scroll-margin を指定
@media (width <= 640px) and (height >= 640px) and (aspect-ratio <= 2/3) {
  .preview-container {
    position: sticky;
    top: 0;
  }
  /* フォーカス時のスペース確保 */
  .app * {
    scroll-margin-top: 100cqw;
  }
}

これでキーボード操作のみで遷移したときにも、フォーカスした要素の上にマージンが確保されるため、固定配置のプレビュー要素に全体が隠れることを回避することができます。

ここでは、コンテナクエリで使用できる 100cqw を指定していますが、この値は固定配置する要素のサイズやレイアウトによって異なります。

固定配置のテクニックは、同時に表示できる要素が増えるため、ついつい取り入れたくなるのですが、アクセシビリティ上の課題を踏まえて、なるべく控えめに使用するのが望ましいです。

実装したときには、キーボード操作のみでのテストや、ビューポートサイズを縮小した状態、ズームした状態でのテストをしてみるとよいかもしれません。

固定配置した要素が重なり、フォーカスが隠れてしまうといった問題が見つかったときには、この記事で説明した以下の方法を試してみるとよいでしょう。

  • 一定以上のビューポートサイズのときのみ固定配置を有効にする(またはその逆)
  • scroll-margin を使用してフォーカス可能な要素に余白を設ける

脚注

  1. 達成基準の名称の和訳は「WCAG 2.2 Candidate Recommendation (勧告候補) | Accessible & Usable」を参考にしました。