知っておくと便利! CSSだけで要素がスクロールできるかどうかを検出する方法

CSSだけで要素がスクロールできるかどうかを検出する方法を紹介します。

先日紹介したスクロール駆動アニメーション(Scroll-Driven Animations)はスクロール可能なオーバーフローがある場合にのみアクティブになるため、要素がスクロール可能かも検出することができます。

CSSだけで要素がスクロールできるかどうかを検出する方法

Solved by CSS Scroll-Driven Animations: Detect if an element can scroll or not
by Bramus!

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

はじめに

スクロール駆動アニメーション(Scroll-Driven Animations)は、スクロール可能なオーバーフローがある場合にのみアクティブになります。そのため、要素がスクロール可能かどうかを検出するメカニズムとしても使用できます。

スペーストグルまたはスタイルクエリを組み合わせると、スクロール可能かどうかに基づいて要素をスタイル設定するために必要なものがすべて揃います。

スクロール駆動アニメーション(Scroll-Driven Animations)について、詳しくは下記をご覧ください。

スクロールをトリガーにしたアニメーションを実装する方法

CSSでの実装が大きく変わる! Scroll-driven Animations スクロールをトリガーにしたアニメーションを実装する方法

CSSで要素がスクロールできるかどうかを検出する

まずは、すぐにそのCSSが知りたい人用にCSSを。

このCSSの使用方法、なぜこれが機能するのか知りたい人は、このまま読み進めてください😉

アクティブと非アクティブなスクロール駆動アニメーション

スクロール駆動アニメーション(Scroll-Driven Animations)は、スクロールによって駆動されるアニメーションです。しかし、アニメーションをするためのスクロール距離がない場合はどうなるでしょうか?

W3Cの仕様ではこれがカバーされており、アニメーションは非アクティブになると記載されています。

プリシンバルボックスが存在しないかスクロールコンテナでない要素である場合、またはスクロール可能なオーバーフローがない場合、ScrollTimelineは非アクティブになります。

これがどういうことなのか、見てましょう。
下記のCSSはhotpinkからlimeまで色を変化させるアニメーションです。

スクロール可能なオーバーフローを持たないスクロールコンテナでは、アニメーションはアクティブにならないので、テキストに設定された色が適用されます。

下記のデモでは、左のコンテナは最初はhotpinkでスクロールするとlineに変化し、右のコンテナは色が変化しません。

See the Pen
Scroll Detection with CSS Scroll-Driven Animations: Inactive Animation
by coliss (@coliss)
on CodePen.

CSSの変数を追加して、スクロール検出機能を作成

CSSの通常のプロパティと同様に、CSSの変数(カスタムプロパティ)もアニメーションさせることができます。
上記のCSSをCSSの変数で記述してみます。

スクロール可能なオーバーフローを持たないスクロールコンテナにスクロール駆動アニメーションとしてアタッチされた場合、CSSの変数の値は設定されていないため、初期値になります。

スクロール検出機能を持たせるには、アニメーションの内部で値が同じ値になるようにします。これは、tofromを同じ値に設定するだけです。

このアニメーションをスクロール駆動アニメーションにフックし、--can-scrollの初期値が0であることを確認すると、完全なコードは下記の通りです。

スクロール可能なオーバーフローを持つ要素ではアニメーションがアクティブになるので、--can-scrollの値は1になります。そして、スクロール可能なオーバーフローを持たない要素では値は0になります。

この値は計算に使用できます。たとえば、下記のように使用します。

このCSSは、スクロール可能なコンテナにlimeの点線でアウトラインが表示され、スクロール不可能な渾天に0pxのアウトラインが表示されます。

See the Pen
Scroll Detection with CSS Scroll-Driven Animations
by coliss (@coliss)
on CodePen.

実装でより使いやすくする

実装での作業を簡単にするため、いくつかのバリエーションを用意しました。

  • スペーストグルを使用する
  • スタイルクエリを使用する

スペーストグルを使用する

スペーストグルの変数は、--can-scrollの初期値にinitialを設定し、アニメーション内の値としてスペースを設定することで、スペーストグルの基本的な仕組みに従います。これにより、数値以外の設定も可能になります。

この実装の唯一の欠点はスペーストグルの基本的な仕組みに慣れていないと、少しコードが読みにくいことです。

See the Pen
Scroll Detection with CSS Scroll-Driven Animations (Space Toggle)
by coliss (@coliss)
on CodePen.

スタイルクエリを使用する

スタイルクエリの変数は、この値の変化に対応するためにスタイルクエリを使用します。これにより、スタイルクエリのポリフィルとしても機能します。
参考: CSSのスタイルクエリの基礎知識と使い方を解説、親要素の「スタイル」に応じて子要素のスタイルを適用

この実装の欠点は、コンテナクエリの子要素にしかスタイルを設定できないこと、そしてこの記事の執筆時点ではChromeのみがスタイルクエリをサポートしていることです。

See the Pen
Scroll Detection with CSS Scroll-Driven Animations (Style Query)
by coliss (@coliss)
on CodePen.

実装例

最近、Shu Ding氏によるスクロール駆動アニメーションを使用した素晴らしいデモを見ました。上下にスクロールするとスクロールインジケーターが表示・非表示になります。

See the Pen
Scroll Timeline
by coliss (@coliss)
on CodePen.

素晴らしいデモですが、問題もあります。コンテンツがスクローラーに対して小さすぎる場合、インジケーターが上下共に表示されてしまいます。

See the Pen
Scroll Timeline (Short Content)
by coliss (@coliss)
on CodePen.

この問題は、この記事で解説したCSSによるスクロール検出が役立ちます。スクロール可能なオーバーフローがある場合にのみインジケーターを表示すればよいのです。インジケーターが表示されていないときにレイアウトがずれないように、条件付きでvisibilityhiddenに設定しておきます。

上記のCSSで問題が解決します。

See the Pen
Conditional Revealing Scroll Indicators Scroll-Timeline
by coliss (@coliss)
on CodePen.

ついでに、CSSを再利用しやすいものにしました。revealキーフレームを0%から2%に制限するのではなく、0%から100%にして範囲全体をカバーするようにしました。次に、animation-range: 20px 40px;を使用して、アニメーションを実行するタイミングを制限します。詳しくは、Xのスレッドをご覧ください。

また、インジケーターではなく、シャドウをつける素晴らしいデモもkizuのブログにあります。

sponsors

top of page

©2024 coliss