【cssのみ】パララックス効果のついた背景の作り方

パララックス背景とは、ページをスクロールした時に、背景と前景の要素を異なる速度で動かすことで、視覚的に奥行きや立体感を演出する視差効果が使われた背景のことです。

Java Scriptを使った実装は知っていたのですが、最近はcssだけでも実装できるようになったのですね。cssのみで実装すると、Java Scriptを使って実装するよりも描画負荷が低く、滑らかに動かすことができる点がメリットです。

実装方法

デモ

まずはデモをご覧ください。

See the Pen パララックス_css by Michi (@Michi_) on CodePen.

今回作成したデモは、画像を上下に動かすことで奥行きを演出しつつ、画像がはみ出したり、隙間ができたりしないように調整しています。

コードの解説

HTML

    <main>
      <section class="parallax-bg bg_01">
        <p>CSS PARALLAX</p>
      </section>
      
      <section class="parallax-bg bg_02">
        <p>CSS PARALLAX</p>
      </section>
      
      <section class="parallax-bg bg_03">
        <p>CSS PARALLAX</p>
      </section>
    </main>

CSS

.parallax-bg {
 overflow: hidden;
  /* この要素が画面を通過するタイムラインに「名前」をつける */
  view-timeline-name: --section-timeline;
  view-timeline-axis: block;
}

.parallax-bg::before{
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 1;
  background-size: cover;
  background-position: center;
  /* @keyframes と スクロールタイムラインの連携 */
  animation: bg-move linear both;
  /* 親要素で定義した名前つきタイムラインを指定する */
  animation-timeline: --section-timeline;
  animation-range: cover 0% cover 100%;
}

@keyframes bg-move {
  from { transform: translateY(10%); }
  to { transform: translateY(-10%); }
}

※ CSSはアニメーションに関連する部分だけ抜き出しています。

まず、パララックス効果付き背景を実装したい要素(.parallax-bg)に、疑似要素を使って背景をつけています。ここでは省略していますが、それぞれのセクションに異なる画像を設定したかったので、bg_01などと名前をつけて個別に設定しています。

画像を動かすアニメーションはキーフレームを使って管理しています。

@keyframes bg-move {
  from { transform: translateY(10%); }
  to { transform: translateY(-10%); }
}

ここの部分ですね。そして、以下のコードで.parallax-bg(親要素)の上端と下端を、アニメーションの開始位置と終了位置として疑似要素に渡すことで、.parallax-bg が画面内を通過している間にアニメーションが動作するようにしています。

.parallax-bg {
  /* この要素が画面を通過するタイムラインに「名前」をつける */
  view-timeline-name: --section-timeline;
  view-timeline-axis: block;
}
.parallax-bg::before{
  /* 親要素で定義した名前つきタイムラインを指定する */
  animation-timeline: --section-timeline;
  animation-range: cover 0% cover 100%;
}

一部を抜粋していますが、親要素である.parallax-bg に view-timeline-name を使うことで、タイムラインに名前をつけ、背景画像を設定している.parallax-bg::before で animation-timeline を使うことで、定義したタイムラインを指定します。

animation-range は、タイムラインに沿ったアニメーションの適用範囲の先頭と末尾を設定できるプロパティで、タイムラインのどこでアニメーションが始まり、どこで終わるかを設定できます。

animation-range: cover 0% cover 100%; というのは、指定された要素の上端がブラウザ下部から現れた瞬間から、指定された要素の下端がブラウザ上部へスクロールされて見えなくなるまでを表します。

つまり、ここでは.parallax-bg の上端がブラウザ下部から出現してから、.parallax-bg の下端がブラウザ上部へと流れて消えるまでを指しています。

こちらのサイトが視覚的にわかりやすく表示してくれるので、よろしければご覧ください。

画像のはみ出し、隙間ができる問題を回避する

疑似要素に指定しているプロパティを見ていただくとわかると思うのですが、画像に inset: -20%; を設定することで、画像が見切れないように大きめに配置しています。このままだと、当然、親要素からはみ出した分の画像もそのまま表示されてしまうので、親要素には overflow: hidden; をつけています。

画像を動かした時に、うっかり隙間(余白)ができてしまって、下の黒い背景が見えてしまう問題も、簡単な計算をすることで回避することができます。

結論から言うと、キーフレームで画像を動かした時の移動量が、背景画像のinset プロパティで広げた分の余白量よりも小さければ隙間ができることはありません。

実際に計算してみましょう。

ここでは、 inset: -20%; を設定しているので、背景画像の実際の高さは 100% + 20% × 2 = 140% ということになります。20%に2をかけているのは、上に20%、下にも20%広がるからです。

次に、キーフレームで設定した数値を見てみます。

@keyframes bg-move {
  from { transform: translateY(10%); }
  to { transform: translateY(-10%); }
}

10%から-10%だから、20%移動していると思いがちですが(私は思いました)、ここでは、0を基準に2つに分けて考えます。つまり、10%から0%、0%から-10%と、それぞれ10%ずつ移動していると思ってください。

この10%を背景画像の実際の高さ140%にかけます。

140% × 10% = 14%

これが画像を動かした時の片側の移動量です。
先ほど、背景画像は上に20%、下にも20%広がっているとお伝えしました。この広がった分量と移動量を比べて、移動量の方が小さければ、移動量が広がった部分におさまるので、隙間はできないということになります。

この場合、14%は20%よりも小さいので、問題ないと言うことになります。

もう一つ例えをあげます。例えば、以下のようにキーフレームを設定したとします。

@keyframes bg-move {
 from { transform: translateY(20%); }
 to { transform: translateY(-10%); }
}

この場合、上部分は20%から0%なので、140% × 20% = 28% となり、広げた分の20%よりも8%大きくなってしまいます。つまり、画像の上端に8%の隙間ができた状態からアニメーションが開始してしまうということです。下端は先ほど計算した通り、140% × 10% = 14% となるため、隙間はできません。

ブラウザの対応状況について

2026年9月1日現在、animation-timeline などを使ったCSSのみでのスクロールに連動したアニメーションは、Chrome、Edge、Safariなどの主要モダンブラウザーで完全対応が進んでいますが、FireFox では未対応(Firefox Nightlyなどの開発版ではプレビュー対応が進められています)です。ご注意ください。

まとめ

今までは JavaScript を使って実装していたスクロールに連動したアニメーションが、CSSだけで手軽に実装できるようになってきているんですね。今回はパララックス効果のある背景を作成してみましたが、ざっとみた感じ、他にもたくさんのことができそうなので、もっといろいろ試してみたいですね。

コメント

タイトルとURLをコピーしました