【CSSのみ】横方向に流れ続ける無限スライドショーの作り方を徹底解説

【CSSのみ】横方向に流れ続ける無限スライドショーの作り方を徹底解説

この記事を書いた人

だいち

PENGIN BLOGメディア編集長。Web業界とは異業種の仕事をしながら、独学でWeb制作の世界に。副業でHP制作やコーディング代行、個人ブログの運営などに取り組み、現在はPENGINにてWebライティングやディレクションをしつつ、メディア運営全般を担当しています。(個人運営ブログ:https://daib-log.com/ )

コンテンツが横方向に自動で流れ続けるスライドショー、と言われてイメージ湧きますでしょうか?

コンベアスライドショーともいいますが、今回はそちらをCSSのみで実装する方法をまとめました。

ECサイトなどで見かけることもありますし、iPhoneの方はApp Storeの中にこのスライドの動きがあるので見てみてください。

デモサイトも用意しているのでこちらもご確認ください。

jQueryのプラグインで実装することが多いですが、実はCSSだけでも結構簡単な記述で実現できますので、コードと合わせて解説していきます。

横並びのレイアウトを作成

<ul class="slideshow">
    <li class="content">tomato</li>
    <li class="content">orange</li>
    <li class="content">blue</li>
    <li class="content">green</li>
</ul>
.content {
  width: 300px;
  height: 300px;
}
.content:nth-child(1) {
  background-color: tomato;
}
.content:nth-child(2) {
  background-color: orange;
}
.content:nth-child(3) {
  background-color: blue;
}
.content:nth-child(4) {
  background-color: green;
}

今こんな感じになっているかと思います。

ブロック縦並び状態

これを横並びにするために.contentの親要素にあたる.slideshowにdisplay: flex;をかけます。

.slideshow {
  display: flex;
}
横並びにした状態

次に要素を連続で流し続けるために同じ内容のslideshowブロックを下に2つ追加します。理由は後述しますが、ついでに.wrapとして親要素で包みます。

<div class="wrap">
 <ul class="slideshow">
    <li class="content">tomato</li>
    <li class="content">orange</li>
    <li class="content">blue</li>
    <li class="content">green</li>
 </ul>
 <ul class="slideshow">
    <li class="content">tomato</li>
    <li class="content">orange</li>
    <li class="content">blue</li>
    <li class="content">green</li>
 </ul>
 <ul class="slideshow">
    <li class="content">tomato</li>
    <li class="content">orange</li>
    <li class="content">blue</li>
    <li class="content">green</li>
 </ul>
</div>

これだけだと当然こうなりますね。

要素を重ねた状態

この3段を一列に並べるために.slideshowの親要素にあたる.wrapに対してdisplay: flex;をかけます。

.wrap {
  display: flex;
}

そうすると一列に並びます。

しかし、要素が画面外にはみ出るので横スクロールが表示されます。

ここではみ出た領域を隠すためのoverflow: hidden;を設定します。また、他パターンで高さが必要になるため予め.contentを包む高さを設定し、align-items: center;で中央揃えにします。

.wrap {
  display: flex;
  align-items: center;
 height: 340px;
 overflow: hidden;
}

ここで下準備は完了なので、ここまでのコードをまとめて記述します。

<div class="wrap">
    <ul class="slideshow">
        <li class="content">tomato</li>
        <li class="content">orange</li>
        <li class="content">blue</li>
        <li class="content">green</li>
    </ul>
    <ul class="slideshow">
        <li class="content">tomato</li>
        <li class="content">orange</li>
        <li class="content">blue</li>
        <li class="content">green</li>
    </ul>
    <ul class="slideshow">
        <li class="content">tomato</li>
        <li class="content">orange</li>
        <li class="content">blue</li>
        <li class="content">green</li>
    </ul>
</div>
.wrap {
  display: flex;
  align-items: center;
 height: 340px;
 overflow: hidden;
}
.slideshow {
  display: flex;
}
.content {
  width: 300px;
  height: 300px;
}
.content:nth-child(1) {
  background-color: tomato;
}
.content:nth-child(2) {
  background-color: orange;
}
.content:nth-child(3) {
  background-color: blue;
}
.content:nth-child(4) {
  background-color: green;
}

スライドアニメーションを設定する

.slideshow {
  display: flex;
  animation: loop-slide 20s infinite linear 1s both;
}
@keyframes loop-slide {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}

animationプロパティを解説

ショートハンドで記述したanimationプロパティを分解します。

animation-name: loop-slide;      /* アニメーション名 */
animation-duration: 20s;        /* 開始から終了までの所要時間 */
animation-iteration-count: infinite; /* アニメーションのループ回数 */
animation-timing-function: linear;  /* 動きの加減速 */
animation-delay: 1s;           /* アニメーションが開始するまでの遅延時間 */
animation-fill-mode: both;            /* アニメーション開始前・終了後の挙動 */

ポイントはanimation-iteration-countを infiniteとし、無限ループを実行させている点です。

また、animation-fill-modeを bothとすることで、アニメーション開始前と終了後にキーフレームアニメーションで指定したプロパティが適用されるので、連続性を表現できます。

keyframesを解説

from { transform: translateX(0);}は開始地点の指定なし=動かしていない状態を意味しています。

to { transform: translateX(-100%); }は親要素(.wrap)の幅100%分左方向に移動させる状態。要は.slideshowに入っている4つのブロックがまるごと画面外に移動して消える、という指定です。

※HTMLに同じ.slideshowを3連続で記述したのも、1つだけだと画面幅より小さくなり、スライドのアニメーションに連続性が持たせられなくなるためだから、ということです。

これでこんな感じのスライドショーが実装できます。

横並びアニメーションgif

ホバー時に動きを止める実装

ここからは必要であれば。

<div class="wrap slide-paused" ontouchstart="">
</div>

hoverさせる用のクラスとして、.wrapと同じタグに.slide-pausedというクラスを付与します。(ontouchstart=”” はスマホタップ時に反応させる為の記述で、スライドアニメーションの動き自体には関係ありません)

.slide-paused:hover .slideshow {
  animation-play-state: paused;
}

.slide-pausedに対してhoverクラスを設定し、子要素の.slideshowに動きをつけます。

animation-play-stateプロパティは、要素にキーフレームアニメーションを適用する場合の動きをつけるもので、pausedを指定すると一時停止にすることができます。これによりhover時にスライドコンテンツが止まることになります。

hoverで止まるスライドgif

ホバー時に要素へ動きを与える

スライドショーの動きとは関係ないですが、おまけで載せておきます。

.contentにホバー時の装飾をつけるためのクラス.content-hoverを追加します。

<li class="content content-hover">tomato</li>
.content-hover {
  transition: all 0.2s;
}
.content-hover:hover {
  transform: translateY(-20px);
  border-radius: 0 10%;
  box-shadow: 0 3px 10px 0 #333;
  opacity: 0.8;
  cursor: pointer;
}
  1. transition: all 0.2s;でホバーした際の動きにスピードをつける
  2. transform: translateY(-20px);で要素を上に移動させる
  3. border-radius: 0 10%;で右上と左下の角を10%丸めます。
  4. box-shadow: 0 3px 10px 0 #333;で影をつけます。
  5. opacity: 0.8;で透明度を上げます。
hoverで形が変わる

デモサイトのコード一覧

改めてデモサイトのコードを記載します。

>> デモサイトはこちらから

<h1>ループで流れる横スライドショー</h1>
      <h2>無限スクロール例1</h2>
      <div class="wrap">
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
      </div>
      <h2>無限スクロール例2(ホバー時にストップ)</h2>
      <div class="wrap slide-paused" ontouchstart="">
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content">tomato</li>
          <li class="content">orange</li>
          <li class="content">blue</li>
          <li class="content">green</li>
        </ul>
      </div>
      <h2>無限スクロール例3(ホバー時にストップ+ピックアップ)</h2>
      <div class="wrap slide-paused" ontouchstart="">
        <ul class="slideshow">
          <li class="content content-hover">tomato</li>
          <li class="content content-hover">orange</li>
          <li class="content content-hover">blue</li>
          <li class="content content-hover">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content content-hover">tomato</li>
          <li class="content content-hover">orange</li>
          <li class="content content-hover">blue</li>
          <li class="content content-hover">green</li>
        </ul>
        <ul class="slideshow">
          <li class="content content-hover">tomato</li>
          <li class="content content-hover">orange</li>
          <li class="content content-hover">blue</li>
          <li class="content content-hover">green</li>
        </ul>
      </div>
* {
  box-sizing: border-box;
  list-style: none;
  padding: 0;
  margin: 0;
}
body {
  padding: 30px 50px;
}
h1 {
  margin-bottom: 100px;
}
h2 {
  margin-bottom: 50px;
}
/* スライドする要素 */
.content {
  width: 300px;
  height: 300px;
}
.content:nth-child(1) {
  background-color: tomato;
}
.content:nth-child(2) {
  background-color: orange;
}
.content:nth-child(3) {
  background-color: blue;
}
.content:nth-child(4) {
  background-color: green;
}
/* スライドレールの枠 */
.wrap {
  overflow: hidden;
  display: flex;
  align-items: center;
  height: 340px;
  margin-bottom: 100px;
}
/* content4つをまとめたスライドブロック */
.slideshow {
  display: flex;
  -webkit-animation: loop-slide 20s infinite linear 1s both;
  animation: loop-slide 20s infinite linear 1s both;
}
@-webkit-keyframes loop-slide {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}
@keyframes loop-slide {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}
/* ホバー時に動きを止める(パターン2・3)*/
.slide-paused:hover .slideshow {
  -webkit-animation-play-state: paused;
  animation-play-state: paused;
}
/* ホバー時の装飾(パターン3) */
.content-hover {
  transition: all 0.2s;
  margin-right: 20px;
}
.content-hover:hover {
  transform: translateY(-20px);
  border-radius: 0 10%;
  box-shadow: 0 3px 10px 0 #333;
  opacity: 0.8;
  cursor: pointer;
}

メディアクエリ のCSSは動きに関係ないのでここには載せてません。

また、上では説明してませんが、デモサイトレイアウト用の要素間marginやベンダープレフィックスなどを記載しています。

まとめ

ECサイトやキャンペーンサイトなどで見かけることがある、横方向自動スクロールの実装方法を解説しました。

しっかり見せたいコンテンツにはあまり適さないアニメーションかと思いますが、要素が多い場合などの装飾としてはいいかと思います。

また、コーディング勉強中の方は自分のエディタにコードをコピペし、数値などをいじりながら変化を見ることでアウトプットするのがオススメです。

シンプルな実装であれば今回のようにCSSのみでも十分かと思うので、参考にしていただけると嬉しいです。

スライダーといえば「カルーセルスライダー」もありますが、こちらの記事で実装方法を解説してるのであわせてご覧ください!


また、当記事を読まれている方の中にはWeb制作初学者の方もいるかと思います。デザインやコーディングの基礎知識を学びたい方向けの記事を用意しているので是非見ていってください!

PENGIN無料コーディング課題

オススメ書籍紹介

オススメUdemy講座紹介