CSSアニメーションで複数の画像をフェード切り替えする

CSSアニメーションで複数の画像をフェード切り替えする

やりたいこと

  • ヒーローイメージを6秒毎に6枚フェードで切り替え。
  • JavaScriptやjQeryは使わずにcssアニメーションで実装。
  • フェードイン後は徐々にズームしていく感じ。

ヒーローイメージを6枚用意

本来ならpicture要素を使ったりしますが
今回はシンプルにstyle属性で背景画像6枚を指定します。

<div class="hero">
  <div class="hero__bg" style="background-image: url(./);"></div>
  <div class="hero__bg" style="background-image: url(./);"></div>
  <div class="hero__bg" style="background-image: url(./);"></div>
  <div class="hero__bg" style="background-image: url(./);"></div>
  <div class="hero__bg" style="background-image: url(./);"></div>
  <div class="hero__bg" style="background-image: url(./);"></div>
</div>

スタイルの指定

親ブロックのスタイル

  • .heroというblockが基準となるのでposition: relative;を指定。
  • スライドの幅や高さを指定。
  • overflow: hidden;で、imgがズームした時にはみ出た部分を隠す。
.hero {
  height: 100vh;
  width: 100%;
  position: relative;
  overflow: hidden;
}

背景画像の共通スタイル

  • 初期値をopacity: 0;にして表示を隠す。
  • position: absolute;で、スライドの中身を.heroに合わせて重ねる。
  • animation: anime 36s 0s infinite;で6枚のスライドを6秒ずつ、36秒間かけてアニメーションし、infiniteによって再生をループ。
.hero__bg {
  position: absolute;
  z-index:10;
  top: 0;
  left: 0;
  opacity: 0;
  width: 100%;
  height: 100vh;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  animation: anime 36s 0s infinite;
}

それぞれの背景画像にアニメーションをつける

animation-delay: で、アニメーションの開始時間を6秒ごとに次の画像が現れるようにずらします。

.hero__bg:nth-of-type(2) {
  animation-delay: 6s;
}
.hero__bg:nth-of-type(3) {
  animation-delay: 12s;
}
.hero__bg:nth-of-type(4) {
  animation-delay: 18s;
}
.hero__bg:nth-of-type(5) {
  animation-delay: 24s;
}
.hero__bg:nth-of-type(6) {
  animation-delay: 30s;
}

Sassを使ってるのであれば、ループで記述しても良いかと思います。

//for文で記述
.hero__bg {
  @for $i from 2 through 6 {
    &:nth-of-type(#{$i}) {
      animation-delay: ($i - 1) * 6;
    }
  }
}

@keyframesの指定

  • opacity: 0;で表示の変更
    transform: scale;でサイズの変更をします。
  • 3秒目から、3秒目かけてフェードイン。
    36秒間かけてアニメーションするので、3秒は8%、6秒は17%。
  • 6秒後に次のスライドが再生されるので、ここからまた3秒目かけてフェードアウト。
    この間、1.2倍まで画像はズームされる。
  • 6枚目よりも1枚目が上に来るようにz-indexを一つ下げる。
@keyframes anime {
  0% {
        opacity: 0;
    }
    8% {
        opacity: 1;
    }
    17% {
        opacity: 1;
    }
    25% {
        opacity: 0;
        transform: scale(1.2) ;
         z-index:9;
    }
    100% { opacity: 0 }
}

サンプルコード

.hero {
  height: 100vh;
  width: 100%;
  position: relative;
  overflow: hidden;
}

.hero__bg {
  position: absolute;
  z-index:10;
  top: 0;
  left: 0;
  opacity: 0;
  width: 100%;
  height: 100vh;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  animation: anime 36s 0s infinite;
}

.hero__bg:nth-of-type(2) {
  animation-delay: 6s;
}
.hero__bg:nth-of-type(3) {
  animation-delay: 12s;
}
.hero__bg:nth-of-type(4) {
  animation-delay: 18s;
}
.hero__bg:nth-of-type(5) {
  animation-delay: 24s;
}
.hero__bg:nth-of-type(6) {
  animation-delay: 30s;
}

@keyframes anime {
   0% {
      opacity: 0;
   }
   8% {
      opacity: 1;
   }
   17% {
      opacity: 1;
   }
   25% {
      opacity: 0;
      transform: scale(1.2);
      z-index: 9;
   }
   100% {
      opacity: 0;
   }
}