CSS だけでスクロールしたタイミングにだけ影がつく実装の解説

この記事は ZOZO Advent Calendar 2022 カレンダー Vol.6の16日目の記事です。

はじめに

こんにちは、たじまです。

この記事では、スクロールした時にだけ影が影がつく実装を JavaScript を使用せず CSS のみで実装する方法の解説書こうと思います。

このヘッダーの下についているような影です

もし違っていたらコメントいただけると嬉しいです!

ソースコード

まずは実際のソースコードを添付します。

時間がある方はプロパティを変えたりして遊んでみてください!

https://codepen.io/schktjm/pen/PoaMQjZ

(Codepen 展開されないの知らなかった...)

解説

スタイルを一部切り抜いてきました。

.scrollbox {
  max-height: 200px;
  width: 250px;
  overflow: auto;

  background: linear-gradient(white 30%, transparent),
    linear-gradient(transparent, white 70%) 0 100%,
    linear-gradient(rgba(0, 0, 0, 0.3) 15%, transparent),
    linear-gradient(transparent, rgba(0, 0, 0, 0.3) 85%) 0 100%;

  background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;
  background-repeat: no-repeat;
  background-color: white;
  background-attachment: local, local, scroll, scroll;
}

これをみてもらえると分かるように、今回 box-shadow を用いた実装にはしていません。

今回影の部分になっているのは background に指定している linear-gradient です。詳しくみていきましょう。

今回ポイントなのは background に指定した4つのグラデーションと background-attachment プロパティです。

魔法1. background-attachment とは

先に background-attachment の解説をします。

background-attachment とは背景を指定した要素がスクロール可能な時に、背景を要素と一緒にスクロールするかビューポートに固定するかどうか指定する CSS プロパティです。

developer.mozilla.org

local: 背景は要素の内容に対する相対位置で固定されます。要素がスクロール機構を持っていた場合、背景画像は要素の内容とともにスクロールします。背景画像の描画エリアと配置エリアは、それらを囲む境界ではなく、要素のスクロール可能なエリアを基準にします。

scroll: 背景は要素自身に対する相対位置で固定され、内容と共にスクロールしません。 (要素の境界に対して効果的に張り付きます。)

つまりまとめると、背景に指定した4つのグラデーションのうち、前2つは要素と共にスクロールし後ろ2つは固定されスクロールされません。

魔法2. 背景の4つのグラデーション

background はカンマ区切りで複数の背景を指定することができます。

  background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;

つまりこの記述は、縦幅が 40px の背景が2つと 縦幅が 14px の背景が2つ存在することがわかります。

4つの背景

  background: linear-gradient(white 30%, transparent),
    linear-gradient(transparent, white 70%) 0 100%,
    linear-gradient(rgba(0, 0, 0, 0.3) 15%, transparent),
    linear-gradient(transparent, rgba(0, 0, 0, 0.3) 85%) 0 100%;

またコチラの記述では背景のグラデーションは

  1. 上から 30% の位置で白から透明になるグラデーション
  2. 上から 70% の位置で透明から白になるグラデーション
  3. 上から 15% の位置でグレーから透明になるグラデーション
  4. 上から 85% の位置で透明からグレーになるグラデーション

であることがわかりました。

4つの背景

魔法のひもとき

なんとなく見えてきました。

つまりこの background は 要素と共に移動する2つのグラデーション と、スクロールせずに固定される 2つのグラデーション であることがわかりました。

図で表すとこういう感じになっています。

からくり

スクロール位置がトップにある場合は、background-attachment の値は local, scroll とはずトップに配置される結果、白色のグラデーションがグレーのグラデーションを覆い見えなくなっていました。 下部にいた時も同じ原理で、下側の白色のグラデーションしか見えていませんでした。

よってスクロール可能な時に box-shadow のような影をつける時ができました。

グラデーションの色を変えると確認できました!

色を変えたバージョン

おわりに

background-attachment は今日で初対面だったため少し間違った紹介をしているかもしれないです。 その時は是非コメントか Twitter で教えてもらえると嬉しいです!

参考にした記事

https://codepen.io/evank/pen/wWbRNO