CSSだけで、一方向に無限に流れるスライドショーを作る

##作りたいもの
こういうやつ。画像が一方向にずっと流れるアニメーション（下はGIF画像なのでカクカクしているけども）。CodePenにも投稿しています（[こちら](https://codepen.io/Mryoo/pen/pYKNOy)）。これを、JavaScriptやjQueryのプラグインを使わずに。CSSのみで作ります。
![1552899979999.gif](https://qiita-image-store.s3.amazonaws.com/0/358159/faa4ac37-bb92-c276-715f-0c2f63a84376.gif)

＊CodePenを開くと画像がすべて読み込まれておらず、ところどころ空欄になってしまっているときがあるかもしれません。その時は、どこかのコードをコメントアウトにし、表示を更新させてから、そのコメントアウトを外して再度表示を更新させると、画像がすべて表示されるようになるかもしれません。

##まずは全部のコード
このスライドショーは、作るのに若干テクニックがいるものです。コードを見ただけで仕組みが分かる人のために、まずは全てのコードを載せておきます。

```html:HTML
<div class="container">
  <div class="slider-container">
    <img src="imgA.jpg" class="slider-img">
    <img src="imgB.jpg" class="slider-img">
    <img src="imgC.jpg" class="slider-img">
    <img src="imgD.jpg" class="slider-img">
    <img src="imgE.jpg" class="slider-img">
    <img src="imgA.jpg" class="slider-img">
    <img src="imgB.jpg" class="slider-img">
    <img src="imgC.jpg" class="slider-img">
    <img src="imgD.jpg" class="slider-img">
    <img src="imgE.jpg" class="slider-img">
  </div>
</div>
```
同じ画像を2回含めていますが、記述ミスではありません。こうする必要があるのです。

```css:CSS
.container {overflow: hidden;}
:root {
  --numOfListA: 5;
  --imgW: 140px;
  --imgH: var(--imgW);
  --mBetweenImg: 50px;
}
.slider-container {
  display: flex;
  font-size: 0;
  animation: slideshow 15s linear infinite;
}
.slider-img {
  width: var(--imgW);
  height:  var(--imgH);
}
.slider-img + .slider-img {margin-left: var(--mBetweenImg);}
@keyframes slideshow {100% {transform: translateX(calc((var(--numOfListA) * var(--imgW) + var(--mBetweenImg) * var(--numOfListA)) * -1));}}
```
カスタムプロパティを使用していますが、使用しなくても作れます。修正が楽なので使っているだけです。
では仕組みを解説していきます。

##仕組み
文章で説明するよりも実際に動いているのを見た方が分かりやすいでしょう。

下のGIFは、画像3枚を無限スライドショーにした際の動きを簡易的に表したものです。本来なら``div.container``に``overflow: hidden;``が指定されていますが、それを指定しないとこういう動きになります。
![1552913772314.gif](https://qiita-image-store.s3.amazonaws.com/0/358159/21758416-8e03-ad95-7683-ebe2bfeb57bb.gif)
imgA・imgB・imgCは``div.slider-container``の中のimgタグ（``img.slider-img``）を表しています。画像と画像の間は``var(--mBetweenImg)``ですね。

ここで、``div.container``に``overflow: hidden;``を指定してやると次のようになります。
![1552914354142.gif](https://qiita-image-store.s3.amazonaws.com/0/358159/4f971320-3207-802a-9a23-9feb647ba4da.gif)
これを見ていただければ、なぜ同じ画像を含めているのかが分かっていただけるのではないでしょうか。文章で説明するとややこしくなりそうなので、文章での説明は省略させていただきます。

##コードの説明
###HTML

```html:HTML
<div class="container">
  <div class="slider-container">
    <!-- リストA -->
    <img src="imgA.jpg" class="slider-img">
    <img src="imgB.jpg" class="slider-img">
    <img src="imgC.jpg" class="slider-img">
    <img src="imgD.jpg" class="slider-img">
    <img src="imgE.jpg" class="slider-img">

    <!-- リストB -->
    <img src="imgA.jpg" class="slider-img">
    <img src="imgB.jpg" class="slider-img">
    <img src="imgC.jpg" class="slider-img">
    <img src="imgD.jpg" class="slider-img">
    <img src="imgE.jpg" class="slider-img">
  </div>
</div>
```
リストAには、スライドショーで流したい画像を入れてください。
リストBには、リストAの画像を**上から同じ順番**で**適当な数**だけ含めてください。なぜそうする必要があるのかは、言葉で説明するとややこしくなりそうなので、これもGIF画像を置くだけにとどめておきます。

●もし上から同じ順番にしなかったら
![1552915568974.gif](https://qiita-image-store.s3.amazonaws.com/0/358159/97e082e3-d0c4-eac9-a94a-280490d007c6.gif)

●もしリストBのimgタグの数が不十分だったら
![1552915660029.gif](https://qiita-image-store.s3.amazonaws.com/0/358159/49d54f39-58e7-1eef-23ed-a786852d32d8.gif)

###CSS
```css:CSS
.container {overflow: hidden;} /* はみ出す部分を見えなくする */
:root {
  --numOfListA: 5; /* リストAのimgタグの数 */
  --imgW: 140px; /* ここで画像の横幅を指定、px指定を推奨 */
  --imgH: var(--imgW); /* ここで画像の縦幅を指定、px指定を推奨 */
  --mBetweenImg: 50px; /* ここで画像間の余白を指定。px指定を推奨 */
}
.slider-container {
  display: flex; /* 画像を横並びにする */
  font-size: 0; /* 余計な余白を削除 */
  animation: slideshow 15s linear infinite;
}
.slider-img {
  width: var(--imgW);
  height:  var(--imgH);
}
.slider-img + .slider-img {margin-left: var(--mBetweenImg);}
@keyframes slideshow {100% {transform: translateX(calc((var(--numOfListA) * var(--imgW) + var(--mBetweenImg) * var(--numOfListA)) * -1));}} /* 下で説明 */
```
アニメーションでの``translateX``の値について説明します。

アニメーションでは、``div.slider-container``を、``0%``ではこの状態で・・・
![155081659966.jpg](https://qiita-image-store.s3.amazonaws.com/0/358159/3f61399a-7b85-2df8-53b1-3b054c51c33f.jpeg)
``100%``ではこの状態に持っていきたい。
![155081659966.jpg](https://qiita-image-store.s3.amazonaws.com/0/358159/d66cfc65-f3b5-e23d-fb42-d0e0b99514a4.jpeg)
ということは、移動量は、リストAの画像の枚数（``var(--numOfListA)``）と``img.slider-img``の横幅（``var(--imgW)``）の**積**と、画像間の余白（``var(--mBetweenImg)``）とリストAの画像の枚数（``var(--numOfListA)``）の**積**の**和**の分だけ左に移動すればよい。左に移動するということはX軸の負の方向に移動するということだから、``-1``をかけてやればよい。

##応用
例えば、パソコンサイズの画面では画像をもっと大きく表示させたいという場合は、メディアクエリを使えばいいです。例えばこういう風に。

```css:CSS
@media screen and (min-width: 900px) {:root {--imgW: 180px;}}
```
下の完成形では、実際にメディアクエリを使用して、画面幅によって画像の大きさを変えています。

##完成形
[こちらのCodePen](https://codepen.io/Mryoo/pen/pYKNOy)に載せています。
下のCSSを追記することで、このスライドショーの仕組みが理解しやすくなるかもしれません。

```css:CSS
body {transform: scale(0.5);}
.container {
  overflow: none;
  border: 5px solid black;
}
```