ホームページで画像を流すスライダー(カルーセル)。
プラグインやライブラリを使えば簡単に実装できますが、たいてい色々なオプションを内蔵しているためにちょっと重めになっていますし、デザインにこだわると結局自分で調整することにもなりますよね。
その点、スライダーを自作すると必要な機能だけで済むので超軽量になりますし、構造に触れるのでデザインも自由自在となります。
今回お伝えするのは、jQueryをちょっとだけ使う最も簡単なスライダーです!
クロスフェードする超シンプルなスライダー
めちゃめちゃ簡単に書けるスライダーです。
クロスフェード(ディゾルブ)で画像が切り替わります。これだと普通の左右に流れるタイプよりはるかに簡単なのです。
See the Pen primary fading slider by Takayuki Kojima (@takayuki-kojima) on CodePen.
HTMLは単純なリスト
HTMLは何の工夫も要りません。
<div class="slider">
<ul class="items">
<li class="item current"><img src=../mt-fuji.jpg"></li>
<li class="item"><img src="../kilimanjaro.jpg"></li>
<li class="item"><img src="../aconcagua.jpg"></li>
<li class="item"><img src="../matterhorn.jpg"></li>
</ul>
</div>
スライダーの枠になる<div>の中に、<ul>でも<div>でもいいのでアイテムを入れるだけ。
アイテムの中身は、今回は画像にしてありますが、何を入れても構いません。
最初に表示させるアイテムにクラス「current」を付けます。
CSSのtransitionでフェードイン・アウト
animationを使ってスクリプトなしにすることも可能ですが、あとあとコントロールボタンなどを実装したいので、大人しくtransitionを使うことにします。
.slider{
width: 100%;
}
.items{
position: relative;
overflow: hidden;
width: 100%;
padding-bottom: 56.25%;
}
.item{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity .6s ease-in-out;
}
.current{
opacity: 1;
}
img{
width: 100%;
height: 100%;
object-fit: cover;
}
枠(.items)のサイズを決める
中に入るアイテムはposition: absoluteなので、枠のサイズは決めておかなければいけません。
幅に対する%値で高さを出せばレスポンシブになるので、heightでなくpaddingで高さを決めます。
中身(.item)を配置、透過させる
全てのアイテム(.item)をposition: absoluteで重ねます。
opacity: 0で透過させ、1枚(.current)だけopacity: 1にして見えるようにします。
このopacityの値をtransitionで操作して、フェードイン・アウトさせます。
画像を枠に収める
アイテムの具である<img>は、object-fit: coverで枠内に収めます。
jQueryはclassを変えるだけ
jQueryでは、次のアイテムにクラス.currentを付け、今のアイテムから.currentを取るという処理を繰り返しているだけです。
function slider(){
var current = $('.item.current'),
next = current.is(':last-child') ? $('.item').first() : current.next();
next.addClass('current');
current.removeClass('current');
}
var setSlider = setInterval( slider, 4000);
コントロールを追加する
コントロール機能も簡単に実装していきます!
See the Pen fading slider 2 by Takayuki Kojima (@takayuki-kojima) on CodePen.
ボタンとドットが追加されていますが、それぞれ分けて解説します。
左右にボタンを付ける
ボタンの配置と処理を付けます。
とりあえず、ここでは後述するドットナビはないものとしてコードを書いてみます。
HTML
div.sliderの中にボタンを入れます。
ボタンは<button>じゃなくても何でもいいです。
<div class=slider>
<ul class=items>...</ul>
<div class=buttons>
<button type=button id=prev class="button prev"></button>
<button type=button id=next class="button next"></button>
</div>
</div>
CSS
ボタンをスライダーの両端に配置します。
.slider{
position: relative;
width: 100%;
}
.items{...}
.item{...}
.buttons{
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.button{
width:32px;
height:32px;
border: none;
outline: none;
padding:0;
background: transparent center no-repeat;
cursor: pointer;
opacity:.4;
&.prev{
background-image: url(../ico_next_b32.png);
}
&.next{
background-image: url(../ico_next_b32-1.png);
}
&:hover{
opacity:.8;
}
}
display: flexを使い、justify-content: space-betweenとalign-items: centerで簡単に両サイドの中央に配置できます。
jQuery
ボタンを付けると、前のアイテムに戻るパターンが加わるため、slider関数にも手を入れます。
function slider(flag) {
var current = $(".item.current"),
next,
index;
if (!flag) {
next = current.is(":last-child") ? $(".item").first() : current.next();
index = next.index();
} else {
next = current.is(":first-child") ? $(".item").last() : current.prev();
index = next.index();
}
next.addClass("current");
current.removeClass("current");
}
var setSlider = setInterval(slider, 4000);
$(".button").on("click", function() {
clearInterval(setSlider);
var flag= $(this).is(".prev") ? true : false;
slider(flag);
setSlider = setInterval(slider, 4000);
});
buttonをクリックしたら、一旦繰り返しを停止、前か次かを判定してsliderを実行、繰り返しを再開、という処理をします。
前に戻るときはtrue、次に進むときはfalseをsliderに渡します。
通常の繰り返し時は引数を渡さないので、次に進むボタンを押したときと同じ動作になります。
ちなみに、単にaddClassしたりremoveClassしたりするだけなので、ボタン連打しても大丈夫です!
ドットナビゲーションを追加する
よく見る、スライダーの下に小さい○○○が並んでいるやつ。何て呼ぶのかよく分からないですが…
上記のボタン追加バージョンに、さらにドットを追加します。
HTML
ボタンの下に、アイテムと同じ数のドットを並べます。
アイテムと同じように、先頭のドットにもクラス「current」を付けておきます。
<div class=slider>
<ul class=items>...</ul>
<div class=buttons>...</div>
<div class=dots>
<button type=button class="dot current"></button>
<button type=button class=dot></button>
<button type=button class=dot></button>
<button type=button class=dot></button>
</div>
</div>
CSS
スライダーの枠からはみ出すように、position: absoluteで下に配置します。
.slider{...}
.items{...}
.item{...}
.buttons{...}
.button{...}
.dots{
position: absolute;
bottom: -20px;
left: 0;
width: 100%;
display: flex;
justify-content: center;
margin-top: 10px;
}
.dot{
display: block;
width: 10px;
height: 10px;
border-radius: 50%;
border: none;
outline: none;
padding: 0;
background: #777;
cursor: pointer;
opacity: .5;
transition: opacity .4s ease-in-out;
&:nth-child(n+2){
margin-left: 5px;
}
&.current{
opacity: 1;
}
}
jQuery
ドットを押したときの処理と、アイテムとドットを連動させる処理を追加します。
function slider(flag, num) {
var current = $(".item.current"),
next,
index;
if (!flag) {
next = current.is(":last-child") ? $(".item").first() : current.next();
index = next.index();
} else if (flag === 'dot') {
next = $(".item").eq(num);
index = num;
} else {
next = current.is(":first-child") ? $(".item").last() : current.prev();
index = next.index();
}
next.addClass("current");
current.removeClass("current");
$(".dot").eq(index).addClass("current").siblings().removeClass("current");
}
var setSlider = setInterval(slider, 4000);
$(".button").on("click", function() {
clearInterval(setSlider);
var flag = $(this).is(".prev") ? true : false;
slider(flag);
setSlider = setInterval(slider, 4000);
});
$(".dot").on("click", function() {
if ($(this).is(".current")) return;
clearInterval(setSlider);
var num = $(this).index();
slider('dot', num);
setSlider = setInterval(slider, 4000);
});
ドットをクリックすると、sliderの第1引数flagに文字列「dot」、第2引数numに何個目のドットがクリックされたのかを数値で渡します。
動作によってsliderの引数flagとnumが受け取る値を整理すると、以下のような感じ。
flagの値 | numの値 | |
---|---|---|
自動再生 | undefined | undefined |
nextボタン | false | undefined |
prevボタン | true | undefined |
ドット | ‘dot’ | 数値(0~) |
これをifで分岐させて、表示させるアイテム(next)と、それが何番目か(index)を確定します。
最後に該当するアイテムとドットをaddClass/removeClassします。
まとめ
最後ドットナビが入ると多少ややこしくはなりますが、いずれしても、かなり少ないコードでできているのではないでしょうか。
こう考えると、スライダーって結構単純な造りなんですよね。
凝ったエフェクトが不要なら、プラグインを使わずに自作で十分かもしれません。
フリック操作への対応や、オーソドックスなスライドをするスライダーは、以下の記事で紹介しています。
コメント