ユーザーにスクロールを予測させるCSSの書き方について
受託案件でレスポンシブ対応をするようになって4年半ほど。未だに悩むのがテーブルのレスポンシブ対応。
テーブル要素をレスポンシブ対応する方法はいろいろとあると思うのですが、私がよく使うのはテーブルをスクロールさせる方法。ただ、このテーブルにはデザインの面で抱えている問題があります。それは、スクロールできることがユーザーには伝わらないこと。ぱっと見、途中でコンテンツが切れているように見えてしまう。もっとひどい場合にはth
やtd
の区切り線と同じタイミングで見切れてしまっていてその先にもっとコンテンツが存在することが予測できない可能性があります。
今回は続きのコンテンツの存在をグラデーションで表現し、CSSのみでスクロールを予測させる方法について記述しています。
実装方法
box-shadow
やbackground
プロパティでグラデーションを適用すればいいと思ってしまいがちですが、ただ単にこのプロパティを適用するだけでは思った表示になりません。
これらのプロパティを適用しても、スクロールし、コンテンツの端っこまで到達しても、その影は消えず、端っこに常に表示さてしまいます。
そこで、CSS Secretの著者であるLea Verouさんのブログでこの問題を解決する方法を見つけました。さらに記事で紹介されているテクニックを参考にして、スクロールテーブルで使うことを前提に、スタイルを作成しました。
See the Pen 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ではlocal
とscroll
を使います。
この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
要素の場合、th
とtd
を差別化するためにth
に背景色が適用されることがよく見られますが、この場合、th
の背景色のほうがレイヤーとして上にあるため、th
だけグラデーションが適用されないという微妙な状態となってしまいます。
そんなときには、th
のbackground-color
プロパティでrgb
の値を色が濃い値に設定し、a
の値を.1
などにして色を薄めると、下層レイヤーにあるはずのグラデーションが無効化されず、背景色を適用しつつグラデーションも適用できる状態になります。
background-attachment
は分裂させる
これが一番個人的にハマってしまったところ。Lea Verouさんの記事でもこの問題には触れられていないからです。
Lea Verouさんの記事の通り実装すると、AndroidのChrome、そしてMacbook Pro(Retina)のChromeで、端にシャドウがつねに残ってしまう状態になってしまいます。
以下、バグが確認できるデモになります。(物好きな方のために用意しました)
See the Pen 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でも両端に到達したときにシャドウが消えるようになりました。