ユーザーにスクロールを予測させるCSSの書き方について

受託案件でレスポンシブ対応をするようになって4年半ほど。未だに悩むのがテーブルのレスポンシブ対応。

テーブル要素をレスポンシブ対応する方法はいろいろとあると思うのですが、私がよく使うのはテーブルをスクロールさせる方法。ただ、このテーブルにはデザインの面で抱えている問題があります。それは、スクロールできることがユーザーには伝わらないこと。ぱっと見、途中でコンテンツが切れているように見えてしまう。もっとひどい場合にはthtdの区切り線と同じタイミングで見切れてしまっていてその先にもっとコンテンツが存在することが予測できない可能性があります。

今回は続きのコンテンツの存在をグラデーションで表現し、CSSのみでスクロールを予測させる方法について記述しています。

実装方法

box-shadowbackgroundプロパティでグラデーションを適用すればいいと思ってしまいがちですが、ただ単にこのプロパティを適用するだけでは思った表示になりません。

これらのプロパティを適用しても、スクロールし、コンテンツの端っこまで到達しても、その影は消えず、端っこに常に表示さてしまいます。

そこで、CSS Secretの著者であるLea Verouさんのブログでこの問題を解決する方法を見つけました。さらに記事で紹介されているテクニックを参考にして、スクロールテーブルで使うことを前提に、スタイルを作成しました。


Scrolling Hints by Responsive Tableのペンを見る。
by Kasumi Morita (@mkasumi) on CodePen.

簡単なScrolling hints の解説

私が手を加えた点についてご紹介する前に、このScrolling hintsというCSSテクニックについて簡単に説明をしたいと思います。(前述したLea Verouさんのブログでは「Pure CSS scrolling shadows」として紹介されていますが、CSS Secretでは「Scrolling hints」という名前で紹介されているようなので、以下、「Scrolling hints」と呼んでこちらのテクニックをご紹介していきます。)

まず、この実装の要となっているのはbackground-attachmentというプロパティです。background-attachmentプロパティには3つの値が用意されています。

scroll
背景画像が要素自身に対して固定され、背景画像は要素の内容とともにスクロールしない
fixed
背景画像がビューポートに対して固定され、要素がスクロール機構を持っていたとしても、背景画像は要素の内容とともに動かない
local
要素がスクロール機構を持っていた場合、背景画像は要素の内容とともにスクロールする

Scrolling hintsではlocalscrollを使います。

このbackground-attachmentプロパティを利用し、さらにシャドウをbackground-imageプロパティで実装できるグラデーションで表現しています。実はこのテクニックでは4つのグラデーションが用意されています。2つは真っ白のグラデーション、そして2つはスクロールできることを表現するためのシャドウとして使用します。

2つの真っ白のグラデーションはそれぞれ左右に配置し、background-attachment: localを指定します。もう2つのシャドウ用のグラデーションにはbackground-attachment: scrollを指定し、これもそれぞれ左右に配置します。

これで基本的なScrolling hintsのテクニックは実装完了です。一見、background-attachment: localを指定した2つの真っ白のグラデーションは必要ないように見えるかもしれませんが、background-attachment: scrollを指定したシャドウ用のグラデーションを削除する役割を担っています。

簡単に説明しましたが、原文を読みたい方はLea Verouさんのブログをご覧ください。

テーブル用にアレンジした点

Lea Verouさんが紹介しているテクニックをそのまま実装して見たのですが、そのままではテーブル用に(そしてデザイン通りに)実装できなかったため、以下の点をアレンジしました。

  • 横スクロール対応
  • スクロール中のシャドウを radial-gradient → linear-gradientに変更
  • th要素の背景色を透過にする
  • background-attachment プロパティは分裂させる

「横スクロール対応」と「スクロール中のシャドウをradial-gradient → linear-gradient に変更」はソースコード見たままなので、他の2つの項目について説明したいと思います。

thの背景色を透過にする

この実装を簡単に説明すると、background-attachmentプロパティを使い、テーブルの端っこまで到達した時にスクロール中に表示している影をbackground-attachment: localと指定した白いグラデーションに上書きさせ、あたかも影がなくなったかのようにみせています。

つまり、backgroundプロパティで実装されています。table要素の場合、thtdを差別化するためにthに背景色が適用されることがよく見られますが、この場合、thの背景色のほうがレイヤーとして上にあるため、thだけグラデーションが適用されないという微妙な状態となってしまいます。

そんなときには、thbackground-colorプロパティでrgbの値を色が濃い値に設定し、aの値を.1などにして色を薄めると、下層レイヤーにあるはずのグラデーションが無効化されず、背景色を適用しつつグラデーションも適用できる状態になります。

background-attachmentは分裂させる

これが一番個人的にハマってしまったところ。Lea Verouさんの記事でもこの問題には触れられていないからです。

Lea Verouさんの記事の通り実装すると、AndroidのChrome、そしてMacbook Pro(Retina)のChromeで、端にシャドウがつねに残ってしまう状態になってしまいます。

以下、バグが確認できるデモになります。(物好きな方のために用意しました)


Scrolling Hints by Responsive Table (Chrome Bug)のペンを見る。
by Kasumi Morita (@mkasumi) on CodePen.

これはChromeのバグで、background-attachmentに複数の値を記述すると起こってしまいます。修正したと書いてあるけれどまだ反映されていないのか、2017年6月15日現在、このバグはまだ残っているようです。

問題の記述は、 background-attachment: local, scroll, local, scrollと指定されていることです。なので、CodePenのデモでは、.table-wrapにスクロール中に適用したいグラデーションとbackground-attachment: scroll、そして内包しているtable要素に両端に表示させたいシャドウとbackground-attachment: localを適用しています。

これで、AndroidのChrome、RetinaディスプレイのMacbook ProのChromeでも両端に到達したときにシャドウが消えるようになりました。


関連エントリー