Flexboxでカルーセルスライダーをつくる


カルーセルスライダーとは、たいていのスライダーは1つの画像などを表示するのに対し、複数のものを表示し、左右の矢印を押下すると、ページャーのようにみえていなかった次の組を表示するもののことを指しています。

できあがったもの

イメージとしてはこんな感じのもの

コード

<div class="carousel">
  <div class="carousel_prev">&lt;</div>
  <div class="carousel_list_outer">
    <ul class="carousel_list">
      <li class="carousel_item">1</li>
      <li class="carousel_item">2</li>
      <li class="carousel_item">3</li>
      <li class="carousel_item">4</li>
      <li class="carousel_item">5</li>
      <li class="carousel_item">6</li>
      <li class="carousel_item">7</li>
      <li class="carousel_item">8</li>
    </ul>
  </div>
  <div class="carousel_next">&gt;</div>
</div>
.carousel{
  display: flex;
  align-items: center;
  width: 100%;
  .carousel_prev,
  .carousel_next{
    padding: 10px;
    cursor: pointer;
    &.hidden{
      visibility: hidden;
    }
  }
  .carousel_list_outer{
    flex: 1;
    overflow: hidden;
  }
  .carousel_list{
    display: flex;
    align-items: center;
    transition: 0.3s;
    .carousel_item{
      flex: 0 0 25%;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 25%;
      height: 100px;
      background-color: #ccc;
      border: 1px solid #fff;
    }
  }
}

簡単に解説

まずは、左右の矢印とカルーセルの表示エリアをFlexboxで横並びにし、カルーセルはflex: 1;で幅いっぱいにする
はみ出た部分を表示したくないのでoverflow: hidden;をつける
もし、左右の矢印ではなく、横スクロールであれば、overflow-x: auto;とすればOK

カルーセル自体もFlexboxで横並びにする
今回は、決まった数を表示し、左右矢印でその数分移動させたかったので、flex: 0 0 25%;として、4つ表示するようにした

あとは、左右の矢印を押下したときに、何かしらの方法で、.carousel_listにクラスをつけるなどし、transform: 'translate(-100%, 0)';などとします
ここの数値のコントロールで、1つずつスクロールさせることもできます

また、Flexboxのorderでも制御することができると思います。

Vue.jsで、左右の矢印を制御する

CSS(Sass)は同じなので割愛します
(最後まできたら、最初に戻らず、矢印を非表示にするタイプです)

<template>
  <div class="carousel">
    <div @click="carouselPrev" class="carousel_prev" :class="{hidden:(list.length<=4) || (carouselIndex===0)}">&lt;</div>
    <div class="carousel_list_outer">
      <ul class="carousel_list" :style="{transform: 'translate(-'+carouselIndex+'00%, 0)'}">
        <template v-for="(item, index) in list">
         <li class="carousel_item">{{item}}</li>
        </template>
      </ul>
    </div>
    <div @click="carouselNext" class="carousel_next" :class="{hidden:(list.length<=4) || (carouselIndex===carouselIndexMax)}">&gt;</div>
  </div>
</template>

<script>
export default {
  layout: "white",
  data(){
    return{
      list: [1, 2, 3, 4, 5, 6, 7, 8],
      carouselIndex: 0,
    }
  },
  computed: {
    carouselIndexMax() {
      return parseInt(this.list.length/4)-1;
    }
  },
  methods: {
    carouselPrev(){
      this.carouselIndex--;
    },
    carouselNext(){
      this.carouselIndex++;
    }
  }
}
</script>