LoginSignup
27
25

More than 5 years have passed since last update.

CSSだけで写真を繰り返し無限に移動(スライド)するアニメーションの方法がすごいので勝手に解説する

Last updated at Posted at 2018-10-27

CSSだけで写真を繰り返し無限に移動する方法がないかなとググったら、自分には思いつかない方法で実装している方がいました!

感謝ですm(__)m

上記の記事では3つの方法が紹介されています。

元の記事に説明があるのでそれを見ていただければ終わりですが、(僕のように)コードを読んでも理解できない方のために勝手に解説します。

元の記事で紹介されている最初の方法のみを解説します。

ちなみにですが、最終的にこんな感じのアニメーションです。

See the Pen oaVgeK by 4cres (@4cres) on CodePen.

コードは下記です。

  <div class="loop_css">
    <img src="img.jpg"><img src="img.jpg">
  </div>
.loop_css {
  position: relative;
  display: -webkit-flex;
  display: flex;
  width: 100vw;
  height: 300px;
  left: 50%;
  margin-left: -50vw;
  overflow: hidden;
}

.loop_css img {
  width: auto;
  height: 100%;
}

/* 1つ目の画像 */
.loop_css img:first-child {
  -webkit-animation: loop 50s -25s linear infinite;
  animation: loop 50s -25s linear infinite;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  will-change: transform;
}

/* 2つ目の画像 */
.loop_css img + img {
  -webkit-animation: loop2 50s  linear infinite;
  animation: loop2 50s linear infinite;
}

/*アニメーション*/
@-webkit-keyframes loop {
  0% {
    -webkit-transform: translateX(100%);
    -ms-transform: translateX(100%);
    transform: translateX(100%);
  }
  to {
    -webkit-transform: translateX(-100%);
    -ms-transform: translateX(-100%);
    transform: translateX(-100%);
  }
}

@keyframes loop {
  0% {
    -webkit-transform: translateX(100%);
    -ms-transform: translateX(100%);
    transform: translateX(100%);
  }
  to {
    -webkit-transform: translateX(-100%);
    -ms-transform: translateX(-100%);
    transform: translateX(-100%);
  }
}

@-webkit-keyframes loop2 {
  0% {
    -webkit-transform: translateX(0);
    -ms-transform: translateX(0);
    transform: translateX(0);
  }
  to {
    -webkit-transform: translateX(-200%);
    -ms-transform: translateX(-200%);
    transform: translateX(-200%);
  }
}

@keyframes loop2 {
  0% {
    -webkit-transform: translateX(0);
    -ms-transform: translateX(0);
    transform: translateX(0);
  }
  to {
    -webkit-transform: translateX(-200%);
    -ms-transform: translateX(-200%);
    transform: translateX(-200%);
  }
}

一つずつポイントとなるところを解説します。

まず img を2つ並べています。親要素の loop_cssdisplay: flex; を指定しているので横並びになります。

今回表示する画像の横幅は 2500px とし、最大の想定表示サイズはフルHDサイズ(1920px)とします。

01.png

同じ画像を読み込んでいますが、イラスト上はわかりやすく色分けして 1 2 と記載します。

左へ移動するアニメーションです。

2500px の画像を2つ並べると 想定最大サイズ 1920px を大きく超えますが、親要素の loop_css  に overflow: hidden; を指定しているので親要素を超える部分は表示されません。

ちなみに親要素の loo_csswidth: 100vw; を指定していますが、vw はスクロールバーの横幅は考慮されません。

スクロールバーが発生するなら width: 100% を指定する方がよいかと思います。

まずは、最初の画像 1 がどのように動くのか見ていきましょう。

translateX(0) は画像を配置した初期値位置なります。

translateX(100%) なら右へ自身の横幅分移動した位置になり、translateX(-100%) なら左へ自身の横幅分移動した位置になります。

02.png

最初の画像は loop_css img:first-child で指定しています。

animation: loop 50s -25s linear infinite; としているため、@keyframes loop のアニメーションが提供されます。

50s はアニメーションの開始から終了までの時間で、-25s はアニメーションが開始される時間です。

-25s なので 25秒早く開始されます。ここが大きなポイントで、アニメーションが開始される時間で初期位置を調整しています。

先ほどの図を見ていただくとわかりますが、アニメーション開始時には translateX(100%) を指定しているので画面外の右側の位置になりますが、-25s を指定することで25秒早い位置、つまり translateX(0) の位置から開始されるということです。

03.png

animationinfinite を指定しているので、アニメーションが無限に繰り返されます。

最初だけは translateX(0) の位置から開始されますが、ループの2回目以降は translateX(100%) の位置から開始されます。

このように指定することで、12 の画像を無限にループして表示することができます。

次は画像 2 の動きを見てみましょう。

04.png

画像 2 の動き簡単です。

画像 2 を配置した初期位置が translateX(0) の位置になり、画面外の右になります。

translateX(0) から translateX(-200%) の位置へ50秒かけて移動します。

このように指定することで画像 12 が隙間なく無限にループ表示されます。

仕組みについて理解できたかと思います。

次は応用して右へ移動するアニメーションを作成してみましょう。

右へ移動するアニメーションを作成

想定表示サイズ 1920px と画像サイズ 2500px は同じで、今度は右へ移動するアニメーションです。

05.png

先ほどのCSSをベースに変更していきます。
先ほどとは逆方向になるので、アニメーションの開始と終了の値を逆にします。

/*アニメーション*/
@-webkit-keyframes loop {
  0% {
    -webkit-transform: translateX(-100%);
    -ms-transform: translateX(-100%);
    transform: translateX(-100%);          /* 先ほどは 100% */
  }
  to {
    -webkit-transform: translateX(100%);
    -ms-transform: translateX(100%);
    transform: translateX(100%);           /* 先ほどは -100% */
  }
}

@keyframes loop {
  0% {
    -webkit-transform: translateX(-100%);
    -ms-transform: translateX(-100%);
    transform: translateX(-100%);          /* 先ほどは -100% */
  }
  to {
    -webkit-transform: translateX(100%);
    -ms-transform: translateX(100%);
    transform: translateX(100%);           /* 先ほどは -100% */
  }
}

@-webkit-keyframes loop2 {
  0% {
    -webkit-transform: translateX(-200%);
    -ms-transform: translateX(-200%);
    transform: translateX(-200%);          /* 先ほどは 0 */
  }
  to {
    -webkit-transform: translateX(0);
    -ms-transform: translateX(0);
    transform: translateX(0);              /* 先ほどは -200% */
  }
}

@keyframes loop2 {
  0% {
    -webkit-transform: translateX(-200%);
    -ms-transform: translateX(-200%);
    transform: translateX(-200%);          /* 先ほどは 0 */
  }
  to {
    -webkit-transform: translateX(0);
    -ms-transform: translateX(0);
    transform: translateX(0);              /* 先ほどは -200% */
  }
}

他のCSSは1つ目の画像と2つの目の画像のアニメーションの開始時間の指定のみ変更しています。
1つの目の画像には -19.2s を、2つ目の画像には 5.8s を指定しています。
なぜ、この指定をするのか詳しく見ていきます。

.loop_css {
  position: relative;
  display: -webkit-flex;
  display: flex;
  width: 100vw;
  height: 300px;
  left: 50%;
  margin-left: -50vw;
  overflow: hidden;
}

.loop_css img {
  width: auto;
  height: 100%;
}

/* 1つ目の画像 */
.loop_css img:first-child {
  -webkit-animation: loop 50s -19.2s linear infinite;
  animation: loop 50s -19.2s linear infinite;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  will-change: transform;
}

/* 2つ目の画像 */
.loop_css img + img {
  -webkit-animation: loop2 50s 5.8s linear infinite;
  animation: loop2 50s 5.8s linear infinite;
}

今回は右へ移動するアニメーションです。
画像 1translateX(-100%) から translate(100%) の位置へ50秒かけて移動します。

06.png

ご覧の通り、translateX(-100%)は画面外の左側の位置ですので、初期位置を画面右端にする必要があります。

07.png

画面の右端にするには画像を右へ 1920px 移動する必要があります。
アニメーションは全体で 5000px を50秒かけて移動します。
1920px 移動するのに何秒かかるか計算しましょう。

1920 / 5000 * 50 = 19.2秒

19.2秒と算出できました。1つ目の画像には animation: loop 50s -19.2s linear infinite; と指定することで、画面の右端からアニメーションが開始されます。

次は画像 2 について見ていきます。
画像 2translateX(-200%) から translate(0) の位置へ 50 秒かて移動します。

08.png

アニメーションの開始位置ですが、translateX(-200%) の位置ではなく、画像 1 の左端の位置にする必要があります。

09.png

580px 移動するのに何秒かかるか計算しましょう。

580 / 5000 * 50 = 5.8秒

2つの目の画像に animation: loop2 50s 5.8s linear infinite; と指定することで 画像1` の左端からアニメーションを開始することができます。

このように指定することで、右へ移動するアニメーションも可能です。

画像の横幅、想定最大表示サイズによって、指定する秒数が異なりますので、利用する場合は自分で計算して指定してください。

safari, iOS で CSS アニメーションが動かない(不安定)

僕の環境で上記のアニメーションを作成したときに、mac の Safari と iOS でアニメーションが開始されたり、されなかったりと動作が不安定でした。

jQueryを使って css を後から読み込むことで解消されました。

同じような方は試してみてください。

1920px以上の表示で左右に白の余白を表示する

想定最大表示サイズが 1920px なので、それ以上で表示したときにはスライドを中央に表示して左右に余白を表示したいですが、スライドに margin:0 auto; の指定ができないので中央に表示できません。
1920px 以上で左右に余白を表示したいときは、下記のように白の余白を左右に配置すれば 1920px で途切れたように表示できます。

@media screen and (min-width : 1920px) {

    .silide1920pxOverSpaceLeft {
        width: calc((100% - 1920px) / 2);
        height: 100%;
        background: #fff;
        position: fixed;
        top: 0;
        left: 0;
        z-index: 9999;
    }
    .slideMenu1920pxOverSpaceRight {
        width: calc((100% - 1920px) / 2);
        height: 100%;
        background: #fff;
        position: fixed;
        top: 0;
        right: 0;
        z-index: 9999;
    }

}
27
25
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
25