一定量スクロールしても背景が変化しないページを作成する - CSS

一定量スクロールしても背景が変化しないページをCSSで作成するコードを紹介します。

概要

スクロールしても一定の間は背景が変化せず、さらにスクロールすると別の背景がスクロールインするページ表現をCSSを利用して表現します。

実装方針

こちらの記事で紹介している、スクロールするとセクションごとに背景画像が変化するページと同様の構造を利用します。 ただし、コンテンツ部分をなくし、すべて背景画像のある枠にて、高さを大きな値にすることで、スクロールしても一定量は背景が動かない状態を表現できます。

実装例1:シンプルな例

以下のHTMLファイルとCSSファイルを作成します。
fixchangeimage-02.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>
  <link rel="stylesheet" href="fixchangeimage-02.css" />
</head>
<body>
  <h3>一定の間は背景が変化せず、さらにスクロールすると別の背景がスクロールインするデモ</h3>
  <div class="pararax_frame1">緑豊かな森林</div>
  <div class="pararax_frame2">活気あふれる都市</div>
  <div class="pararax_frame3">美しい水辺</div>
  <div class="pararax_frame4">先進的な技術力</div>
  <div class="pararax_frame5">宇宙をつなぐ交通の要衝</div>
</body>
</html>
fixchangeimage-02.css
body {
  margin: 0 0 0 0;
  padding:0 0 0 0;
}

.content_frame {
  height: 4rem;
}

.pararax_frame1 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;

  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-01.png");
}
.pararax_frame2 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;

  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-02.png");
}
.pararax_frame3 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-03.png");
}
.pararax_frame4 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;

  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-04.png");
}
.pararax_frame5 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;

  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-05.png");
}

イメージ

表示する画像のimg-01.png ~ img-05.pngは以下を利用します。

解説

こちらの記事での実装例と異なり、背景画像のある枠を連続で並べています。
  <div class="pararax_frame1">緑豊かな森林</div>
  <div class="pararax_frame2">活気あふれる都市</div>
  <div class="pararax_frame3">美しい水辺</div>
  <div class="pararax_frame4">先進的な技術力</div>
  <div class="pararax_frame5">宇宙をつなぐ交通の要衝</div>

heightを1800pxに設定し、画面の高さより大きい値にしています。他の設定は、背景画像を固定する設定や内部のテキストを中心にそろえる設定になります。
.pararax_frame1 {
  display: flex;
  font-size: 2.6rem;
  color: #FFFFFF;
  align-items: center;
  justify-content: center;

  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-01.png");
}

実行結果

プロジェクトを実行します。下図のページが表示されます。


ページを下にスクロールします。背景は変化しません。しばらくするとテキストがスクロールインします。さらにスクロールしても背景は変化しません。


さらにスクロールすると次の背景がスクロールインします。


ページを下にスクロールします。背景は変化しません。しばらくするとテキストがスクロールインします。さらにスクロールしても背景は変化しません。


続けてスクロールすると、3つめ、4つ目の背景が順番にスクロールインします。






背景画像がスクロールインしてもしばらくの間画面をスクロールし続けても背景が移動しない動作が実装できました。

実装例2:応用例

CSS Scroll Driven Animaionを組み合わせて、スクロールに応じてコンテンツが表示される例です。
以下のHTMLファイルとCSSファイルを作成します。
fixchangeimage-03.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>
  <link rel="stylesheet" href="fixchangeimage-03.css" />
</head>
<body>
  <h3>一定の間は背景が変化せず、さらにスクロールすると別の背景がスクロールインするデモ</h3>
  <div class="pararax_frame1">
    <div class="frame1_caption">緑豊かな森林</div>
    <div class="frame1_text">
      大森林への旅立ちを夢見るあなたへ。ここには、無限の緑と神秘が息づいています。
      大森林は、自然の驚異と生命の宝庫が共存する、この世界でも稀有な場所の一つです。美しい木々が空高く伸び、その枝葉は天を覆うかのように広がっています。
      森の深い部分では、幾重にも重なる木々が光を遮り、静寂と神秘に満ちた空間を作り出します。しかし、怖れることはありません。
      そこには、生命が息吹き、あなたを温かく迎え入れてくれる存在たちがいます。
    </div>
  </div>
  <div class="pararax_frame2">
    <div class="frame2_caption">活気あふれる街並み</div>
    <div class="frame2_text">
      ここは、夢と冒険が交差する場所。尖塔が空に向かってそびえ立ち、美しい景観を築き上げるこの都市は、あらゆる旅人や商人たちの憩いの場となっています。
      この街の中心には、生命と活動の源泉である市場が広がっており、豊かな色彩と賑わいでいつも溢れています。
      朝露に濡れる野菜や、香り高いハーブ。果実はその色鮮やかさで目を引き、種々のスパイスが異国情緒を演出します。
      ここでは、最も新鮮で質の高い食材が手に入り、それらを使った料理は訪れる者の心を豊かにしてくれます。
      露店には、手作りのパンやチーズ、さらには珍しいお菓子まで、あらゆる味覚を刺激する逸品が揃っています。
    </div>
  </div>
  <div class="pararax_frame3">
    <div class="frame3_caption">美しい水辺</div>
    <div class="frame3_text">
      透明で穏やかな川面が、まるで鏡のように山々と空を映し出すこの地は、まさに地上の楽園です。
      川のせせらぎが奏でる穏やかな音楽と、断崖に生い茂る樹木の緑が鮮やかに融合し、圧倒的な美しさを創り出しています。
      この場所は、まるで時間が止まったかのように、訪れる人々に平和と静寂を提供します。
      風光明媚なこの地域の真珠とも言えるのが、高い岩山です。その荘厳な姿は、遠くからでも一目でその存在を感じさせます。
      太陽の光が岩肌に反射する様は、まるで山全体が光り輝いているかのようです。霧の日には、その峰々が霧の中に浮かび上がり、神秘的な雰囲気を醸し出します。
      この幻想的な景観は、訪れる人々の心に深い印象を残すことでしょう。
    </div>
  </div>
  <div class="pararax_frame4">
    <div class="frame4_caption">眠らない都市</div>
    <div class="frame4_text">
      光と影が織りなす、このハイテク都市があなたを待っています。
      ここでは、星空をも凌ぐ高層ビルが夜空に向かってそびえ立ち、その輝きはまるで夢のよう。
      夜になると、ネオンの光が都市全体を鮮やかに照らし出し、眠らない都市の活気と魅力を際立たせます。
      この光の海は、訪れる人々に未来への希望とインスピレーションを与えます。
      この都市の交通網は、その発展度と利便性で知られています。最先端の公共交通システムは、都市の隅々までを結び、時間を問わずスムーズに移動することができます。
      空中タクシーや高速移動のチューブトレインなど、革新的な移動手段が日常生活に溶け込んでおり、快適で便利な生活を実現しています。
    </div>
  </div>
  <div class="pararax_frame5">
    <div class="frame5_caption">宇宙交通の要衝</div>
    <div class="frame5_text">
      惑星の上空に浮かぶ、壮大な宇宙ステーションが新たな冒険の拠点として、あなたを待っています。
      この宇宙ステーションは、宇宙と物流、交通を結ぶ中心地であり、無限の可能性を秘めた要衝です。
      星々を結ぶ門とも言えるこの場所は、あらゆる人々と物資の交流の中心地となっています。
      巨大なドックには、常に多くの旅客船が行き交います。ここから近くの惑星への短距離旅行も、遠く離れた星系への長距離移動も可能です。
      このステーションは、宇宙の各地から来た旅行者や商人、冒険家たちで賑わい、多種多様な文化や情報が交わる場所です。
      まさに、宇宙の十字路に位置する中核宇宙ステーションです。
    </div>
  </div>
</body>
</html>
fixchangeimage-03.css
body {
  margin: 0 0 0 0;
  padding:0 0 0 0;
}

.content_frame {
  height: 4rem;
}

.pararax_frame1 {
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-01.png");
}
.pararax_frame2 {
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-02.png");
}
.pararax_frame3 {
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-03.png");
}
.pararax_frame4 {
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-04.png");
}
.pararax_frame5 {
  height: 1800px;
  background-attachment: fixed;
  background-size: cover;
  background-image: url("res/img-05.png");
}

.frame1_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame1-caption-progress linear;
  animation-timeline: scroll();
}
.frame2_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame2-caption-progress linear;
  animation-timeline: scroll();
}
.frame3_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame3-caption-progress linear;
  animation-timeline: scroll();
}
.frame4_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame4-caption-progress linear;
  animation-timeline: scroll();
}
.frame5_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame5-caption-progress linear;
  animation-timeline: scroll();
}

.frame1_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame1-text-progress linear;
  animation-timeline: scroll();
}

.frame2_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame2-text-progress linear;
  animation-timeline: scroll();
}

.frame3_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame3-text-progress linear;
  animation-timeline: scroll();
}

.frame4_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame4-text-progress linear;
  animation-timeline: scroll();
}

.frame5_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame5-text-progress linear;
  animation-timeline: scroll();
}

@keyframes frame1-caption-progress {
  0% {
    transform: translateY(400px);
  }
  2% {
    transform: translateY(0px);
  }
  15% {
    transform: translateY(0px);
  }
  20% {
    transform: translateY(-240px);
  }
  100% {
    transform: translateY(-240px);
  }
}

@keyframes frame2-caption-progress {
  0% {
    transform: translateY(1800px);
  }
  20% {
    transform: translateY(1800px);
  }
  25% {
    transform: translateY(0px);
  }
  35% {
    transform: translateY(0px);
  }
  40% {
    transform: translateY(-240px);
  }
  100% {
    transform: translateY(-240px);
  }
}

@keyframes frame3-caption-progress {
  0% {
    transform: translateY(1800px);
  }
  40% {
    transform: translateY(1800px);
  }
  45% {
    transform: translateY(0px);
  }
  55% {
    transform: translateY(0px);
  }
  60% {
    transform: translateY(-240px);
  }
  100% {
    transform: translateY(-240px);
  }
}

@keyframes frame4-caption-progress {
  0% {
    transform: translateY(1800px);
  }
  62% {
    transform: translateY(1800px);
  }
  67% {
    transform: translateY(0px);
  }
  80% {
    transform: translateY(0px);
  }
  85% {
    transform: translateY(-240px);
  }
  100% {
    transform: translateY(-240px);
  }
}

@keyframes frame5-caption-progress {
  0% {
    transform: translateY(1800px);
  }
  85% {
    transform: translateY(1800px);
  }
  90% {
    transform: translateY(0px);
  }
  100% {
    transform: translateY(0px);
  }
}

@keyframes frame1-text-progress {
  0% {
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  20% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@keyframes frame2-text-progress {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  40% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@keyframes frame3-text-progress {
  0% {
    opacity: 0;
  }
  45% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  60% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@keyframes frame4-text-progress {
  0% {
    opacity: 0;
  }
  65% {
    opacity: 0;
  }
  75% {
    opacity: 1;
  }
  85% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@keyframes frame5-text-progress {
  0% {
    opacity: 0;
  }
  90% {
    opacity: 0;
  }
  95% {
    opacity: 1;
  }
}

解説

背景を指定して背景を固定した枠の内部に、見出し用の frame1_caption クラスの枠と、コンテンツ用のframe1_textの枠を記述しています。
  <div class="pararax_frame1">
    <div class="frame1_caption">緑豊かな森林</div>
    <div class="frame1_text">
     <!-- (中略) -->
    </div>
  </div>

見出しのframe1_caption クラスの設定は下記コードです。 position: fixed; に設定し親の枠の位置を基準としています。見出しは下からスクロールする設定でコンテンツが表示されている間は上部にとどまり、 背景が切り替わるタイミングでスクロールアウトします。
.frame1_caption {
  color: #FFFFFF;
  top: 2rem;
  left: 1rem;
  font-size: 3.2rem;
  position: fixed;
  animation: frame1-caption-progress linear;
  animation-timeline: scroll();
}

@keyframes frame1-caption-progress {
  0% {
    transform: translateY(400px);
  }
  2% {
    transform: translateY(0px);
  }
  15% {
    transform: translateY(0px);
  }
  20% {
    transform: translateY(-240px);
  }
  100% {
    transform: translateY(-240px);
  }
}

コンテンツのframe1_text クラスの設定は下記コードです。 position: fixed; に設定し親の枠の位置を基準としています。コンテンツはスクロールに応じてフェードインする設定にしています。 背景が表示されている間は表示し、背景が切り替わるタイミングでフェードアウトします。
.frame1_text {
  color: #FFFFFF;
  padding: 1rem 1rem 1rem 1rem;
  font-size: 2rem;
  position: fixed;
  top: 120px;
  left: 0;
  animation: frame1-text-progress linear;
  animation-timeline: scroll();
}

@keyframes frame1-text-progress {
  0% {
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  20% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

他の枠も同じ動作で実装します。

実行結果

上記のHTMLファイルをWebブラウザで表示します。 下図のページが表示されます。


スクロールすると、見出しが上までスクロールして停止します。同時にコンテンツの文章がフェードインして表示されます。


さらにスクロールするとコンテンツがフェードアウトし、見出しが上にスクロールアウトします。


次の背景がスクロールインすると、下から見出しがスクロールインして、上部で止まります。同時に本文のテキストがフェードインします。


さらにスクロールするとコンテンツがフェードアウトし、見出しが上にスクロールアウトします。次の背景画像がスクロールインします。


スクロールするとコンテンツがフェードアウトし、見出しが上にスクロールアウトします。次の背景画像がスクロールインします。


スクロールすると、見出しが上までスクロールして停止し、コンテンツの文章がフェードインして表示されます。


スクロール量に応じて、コンテンツがフェードインしたり、スクロールインして停止する挙動をCSSで実装できました。

著者
iPentecのメインデザイナー
Webページ、Webクリエイティブのデザインを担当。PhotoshopやIllustratorの作業もする。
最終更新日: 2024-07-02
作成日: 2024-03-31
iPentec all rights reserverd.