Unformed Building

スクロール・コンテナーへのアクセス

公開:

パーマリンク

ウェブページ内には、しばしばスクロール可能な要素が存在します。スクロール可能な要素のことをスクロール・コンテナーと呼びますが、それらの要素のコンテンツをすべて閲覧するにはスクロールが必要になります。
何を当たり前のことを言っているのかと思われるでしょうが、マウスのみ、またはキーボードのみの環境でもスクロールを完了させることが可能なのでしょうか。

キーボード操作のみでのアクセス

ホイール機能のついたマウスにおいては、スクロール・コンテナーまでカーソルを移動し、ホイールを実行することでスクロールが可能です。

それに対し、キーボードではスクロール・コンテナー自身、またはそのコンテンツ内にフォーカスを移動しなければカーソルキーや、その他スクロール操作を行うキーによるスクロール動作を行うことができません。

iframetextareaなど、初期状態でスクロールが可能な要素は、tabindex属性を指定せずともキーボード・ナビゲーションによるアクセスは基本的に可能です。
しかし、そうではない要素に対し、ページの著者がCSSでoverflowプロパティ(overflo-xoverflow-yも含む)をscrollautoにした場合はどうでしょうか。

HTML Living Standard - 6 User interaction」の「Focusable area」には次の文が含まれています。

The scrollable regions of elements that are being rendered and are not expressly inert.

HTML Living Standard - 6 User interaction - Focusable area

inert(不活性)ではないスクロール領域はフォーカス可能である、ということがHTMLの仕様に掲載されていることがわかります。

デモを作成しましたので、ご確認ください。
以下はデモページのHTMLとCSSの断片です。

<div class="content">
  <p class="scrollable">
    ...
  </p>
</div>
:focus {
  outline-width: 2px;
  outline-style: solid;
  outline-color: skyblue;
  outline-offset: 2px;
}

.content {
  border-width: 1px;
  border-style: solid;
  border-color: gray;
  padding: 1em;
  width: 20em;
}

.scrollable {
  margin: 0;
  overflow: auto;
  height: 10em;
}

それぞれのp要素にはoverflow: autoが指定されています。3種類のケースの違いは次のとおりです。

Case 1-A
スクロールの必要がない程度のコンテンツ
Case 1-B
スクロールが必要な量のコンテンツ
Case 1-C
スクロールが必要な量のコンテンツで、内部にボタンがある

どうですか、すべてのケースでマウス、またはキーボードで最後まで見られましたか。
キーボードのみの操作ではFirefox以外を利用している方は見られなかったのではないかと思います。

先ほど示した仕様に準拠しているのは、2020年3月現在、Firefoxのみです。

Chrome(というよりBlinkエンジン)では該当イシュー「Issue 585413: Scrollable area does not get focus with TAB focus navigation」は2019年にFixedになっているものの、動作していないように見えます。
これは現段階ではフラグ付きの実装のためです。chrome://flagsから「Experimental Web Platform features」を有効にすることで動作を確認できます。

Safari(Webkit)については特に見つかりませんでした。
またMicrosoft Edge レガシ、Internet Explorerでも動作しません。

このような状況で、スクロール・コンテナー内のコンテンツにアクセスするにはどうしたらよいのでしょう。
キーボードでフォーカス可能な要素がコンテンツ内にある場合はスクロール位置がそこまで移動してしまうものの、要素のスクロール自体はキーボードのみで可能です。
そうではない場合、スクロール・コンテナーへフォーカス可能でないブラウザーの利用者はキーボードでアクセスできないのでしょうか。

思いつくのはスクロール・コンテナーである要素にtabindex属性を付与し、その値を0以上にすることです。
これはシンプルでスマートな解決法に見えます。

該当要素にoverflow: scrollが指定されているのならば、この方法はうまくいくでしょう。

しかし、overflow: autoの場合はどうでしょうか。スクロールの必要がない量のコンテンツの場合、特に意味のないフォーカス可能要素が生まれてしまいます。致命的な現象ではありませんが、違和感のある動作になってしまいます。

これを解消するには、JavaScriptの力が必要となります。
該当要素の矩形と、コンテンツ量に応じて必要とされる矩形を比較し、tabindex属性をつけ外しすることになります。
また、レスポンシブなレイアウトにおいては、要素のサイズを監視する必要もあるでしょう。

当然それには制作コストがかかります。
Firefoxは対応済み、Blink系統のブラウザーもそのうちフラグが外れるでしょう。こういった状態で追加コストで対応するかどうかはチームで判断するしかないでしょう。

  • ページ内のコンテンツにスクロールが必要なパーツを作らない
  • スクロールの必要があるのならば、overflow: scrolltabindex属性を指定し、コンテンツ量によってはスクロールの必要がない状態でもスクロールバーが表示されるのを許容する
  • それもできないのならばJavaScriptで頑張る
  • そもそも仕様ではスクロール・コンテナーはフォーカス可能であり、対応も進みつつあるので何もしない

といった選択肢があります。
いえ、わたしが思いつかないだけできっともっとあるでしょう。

マウスとキーボードを併用している場合

レアケースかと思いますが、マウスでスクロール・コンテナーにアクセスし、スクロール操作自体はキーボードで行う場合があります。

わたしがそうなのですが、スクロール・コンテナー内の任意を場所をクリックし、カーソルキーでスクロールをすることがあります。
事情としてはマウスを頻繁に長時間使い続けて右手首の腱鞘炎を起こしたことがあり、マウスに触れる時間を少しでも減らそうとした、というものです。

マウスの利便性を保ちつつ、非常に単純な操作はキーボードで済ませる、という使用方法です。

既出のデモページで、同様の操作(スクロール・コンテナー内をクリックしたあとでカーソルキーでスクロール)を行ってみてください。
問題なく操作できるはずです。

しかし、この操作方法が不可能なパターンがあります。
それはスクロール・コンテナーの先祖にtabindexが指定されている場合です。

先ほどと同様にデモを作りましたのでご覧ください。
1つ目のデモのスクロール・コンテナーの親要素にtabindex="0"を追加したものです。

スクロール・コンテナー内をクリックすると、その親にフォーカスを奪われるのでスクロール・コンテナーをキーボードで操作できません。
これはスクロール・コンテナーにキーボードでフォーカス可能なFirefoxでも同様です。

これを回避するには、やはりスクロール・コンテナー自体にtabindex属性を付与するしかないのですが、すでに述べたように、この方法にはいくつかの解決すべき問題があります。

この現象に遭遇するパターンとしては、わたしのような使い方をしている場合、または、ホイール機能のないマウスを利用していて、結果としてわたしと同じような操作をしている場合でしょう。

非常に限定的なパターンかつレアケースではあると思いますが、このようなシチュエーションも存在します。


この記事を書くきっかけとしては「しんぷるはてぶ」を作っていたときにキーボードでうまくスクロール操作ができなかったことです。シチュエーションとしてはマウスとキーボードの併用です。
なお、「しんぷるはてぶ」ではスクロールが必要なコンテンツには大量のリンクが存在し、アクセスするのに不便ではないので特別な対応はしていません。

現象に気づいた際に話し相手になってくれた矢倉さん(@myakura)、ありがとうございました。

以下は参考資料です。