STEP 1|HTMLの骨格だけ書く
まず index.html に最低限の構造を書きます。
この時点では見た目は気にしません。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>スライダー</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/layout.css">
</head>
<body>
<div class="slider">
<ul class="slider-inner">
<!-- ここにスライド画像が入る(あとでJSが自動生成) -->
</ul>
<ul class="nav">
<!-- ここにドットナビが入る(あとでJSが自動生成) -->
</ul>
<p id="arrow-prev" class="arrow">←</p>
<p id="arrow-next" class="arrow">→</p>
</div>
<script src="js/index.js"></script>
</body>
</html>
STEP 2|画像を1枚だけ手で書いて表示を確認する
JavaScriptで自動生成する前に、HTMLに直接 <li> を書いて表示を確認します。
まず「1枚表示できるか」を確認するのが大事です。
<ul class="slider-inner"> の中に追記します:
<ul class="slider-inner">
<li><img src="images/img01.jpg"></li>
</ul>
あわせて layout.css にスライダーの大枠だけ書きます:
.slider {
position: relative;
width: 640px;
height: 480px;
margin: 0 auto;
}
.slider .slider-inner {
position: relative;
width: 100%;
height: 100%;
}
.slider .slider-inner li {
width: 100%;
height: 100%;
}
.slider .slider-inner li img {
width: 100%;
height: 100%;
object-fit: cover;
}
STEP 3|画像を複数枚並べて「重なり」を作る
次に <li> を4枚分手書きして、フェード切り替えの準備をします。
CSSで全画像を重ねて、最初の1枚だけ表示する状態を作ります。
HTMLに残り3枚を追加:
<ul class="slider-inner">
<li class="show"><img src="images/img01.jpg"></li>
<li><img src="images/img02.jpg"></li>
<li><img src="images/img03.jpg"></li>
<li><img src="images/img04.jpg"></li>
</ul>
CSSに重なりとフェードの仕組みを追加:
.slider .slider-inner li {
position: absolute; /* 全画像を同じ位置に重ねる */
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0; /* 初期状態は全部非表示 */
transition: all 600ms; /* フェードのアニメーション速度 */
pointer-events: none;
}
/* .show クラスが付いた1枚だけ表示 */
.slider .slider-inner li.show {
opacity: 1;
z-index: 1;
pointer-events: auto;
}
STEP 4|矢印とドットのスタイルを整える
見た目を仕上げておきます。
/* ドットナビ全体 */
.slider .nav {
width: 100%;
margin-top: 20px;
text-align: center;
font-size: 0;
}
/* ドット1つ */
.slider .nav li {
display: inline-block;
width: 15px;
height: 15px;
margin: 0 5px;
border-radius: 15px;
background: #ddd;
cursor: pointer;
transition: background 400ms;
}
.slider .nav li:hover { background: #aaa; }
.slider .nav li.current { background: #aaa; }
/* 矢印 */
.slider .arrow {
position: absolute;
top: 50%;
font-size: 20px;
cursor: pointer;
width: 20px;
height: 40px;
background: #000;
color: #fff;
line-height: 40px;
padding: 5px;
transition: opacity 400ms;
}
.slider .arrow:hover { opacity: 0.7; }
.slider .arrow#arrow-prev { left: 0; transform: translate(-100%, -50%); }
.slider .arrow#arrow-next { right: 0; transform: translate(100%, -50%); }
STEP 5|JavaScriptでliタグを自動生成するように書き換える
STEP 2〜3 でHTMLに手書きした <li> を削除して、
JavaScriptで自動生成するように書き換えます。
まず index.html の <li> を全部削除して元の空の状態に戻します:
<ul class="slider-inner"></ul>
<ul class="nav"></ul>
次に js/index.js に以下を書きます:
// スライダーに表示する画像のパス
var imgList = [
"images/img01.jpg",
"images/img02.jpg",
"images/img03.jpg",
"images/img04.jpg"
];
// 画像とナビの <li> を自動で追加
for (var i = 0; i < imgList.length; i++) {
// 画像スライドの <li> を生成して追加
var slide = document.createElement("li");
slide.innerHTML = "<img src='" + imgList[i] + "'>";
document.getElementsByClassName("slider-inner")[0].appendChild(slide);
// ドットナビの <li> を生成して追加
var nav = document.createElement("li");
nav.setAttribute("data-nav-index", i);
document.getElementsByClassName("nav")[0].appendChild(nav);
}
STEP 6|変数を定義して、最初の1枚を表示させる
JSで生成した要素を変数に入れて扱いやすくし、
最初の画像とドットを表示状態にします。
js/index.js に追記:
// 各要素を変数に入れる
var length = imgList.length - 1;
var imageSlide = document.getElementsByClassName("slider-inner")[0].getElementsByTagName("li");
var dotNavigation = document.getElementsByClassName("nav")[0].getElementsByTagName("li");
var nowIndex = 0;
// 最初の1枚に表示クラスを付ける
imageSlide[nowIndex].classList.add("show");
dotNavigation[nowIndex].classList.add("current");
STEP 7|切り替え関数を作り、コンソールでテストする
スライド切り替えの関数 sliderSlide() を書きます。
まだ矢印クリックには繋げず、コンソールから手動で呼び出して動作確認します。
js/index.js に追記:
// 切り替え処理の本体
function sliderSlide(val) {
// 今の枚からクラスを外す
imageSlide[nowIndex].classList.remove("show");
dotNavigation[nowIndex].classList.remove("current");
// インデックスを更新して次の枚にクラスを付ける
nowIndex = val;
imageSlide[nowIndex].classList.add("show");
dotNavigation[nowIndex].classList.add("current");
}
sliderSlide(1) // → 2枚目に切り替わるはず
sliderSlide(2) // → 3枚目に切り替わるはず
sliderSlide(0) // → 1枚目に戻るはず
フェードしながら画像が切り替わればOKです。
STEP 8|矢印クリックでスライドするようにする
関数が動くことを確認できたら、矢印にイベントを繋ぎます。
js/index.js に追記:
// ← 前へ矢印
document.getElementById("arrow-prev").addEventListener("click", function() {
var index = nowIndex - 1;
if (index < 0) { index = length; } // 0を下回ったら末尾へ
sliderSlide(index);
}, false);
// → 次へ矢印
document.getElementById("arrow-next").addEventListener("click", function() {
var index = nowIndex + 1;
if (index > length) { index = 0; } // 末尾を超えたら先頭へ
sliderSlide(index);
}, false);
STEP 9|ドットナビをクリックできるようにする
ドットをクリックしたとき、対応する番号の画像に直接ジャンプするようにします。
js/index.js に追記:
// ドットナビ
for (var i = 0; i < dotNavigation.length; i++) {
dotNavigation[i].addEventListener("click", function() {
var index = Number(this.getAttribute("data-nav-index"));
sliderSlide(index);
}, false);
}
STEP 10|連打防止を追加して完成
最後の仕上げです。アニメーション中に素早くクリックを繰り返すと
スライドが壊れることがあります。フラグで防ぎます。
sliderSlide() 関数を以下のように書き換えます:
// 追加:アニメ中フラグ
var isChanging = false;
var slideTimer;
function sliderSlide(val) {
// アニメ中なら何もしない(連打防止)
if (isChanging === true) { return false; }
isChanging = true;
// 今の枚からクラスを外す
imageSlide[nowIndex].classList.remove("show");
dotNavigation[nowIndex].classList.remove("current");
// 次の枚にクラスを付ける
nowIndex = val;
imageSlide[nowIndex].classList.add("show");
dotNavigation[nowIndex].classList.add("current");
// CSSのtransitionと同じ600ms後にフラグを解除
slideTimer = setTimeout(function() {
isChanging = false;
}, 600);
}
まとめ
| STEP | やること | 確認ポイント |
|---|---|---|
| 1 | HTML骨格を書く | 矢印「← →」が表示される |
| 2 | 画像を1枚手書きで表示 | 画像が1枚表示される |
| 3 | 複数枚重ねてフェードの仕組みを作る | devツールでクラスを移すと切り替わる |
| 4 | 矢印・ドットのスタイルを整える | 見た目が整っている |
| 5 | JSで <li> を自動生成 |
devツールで <li> が4つ生成されている |
| 6 | 変数定義・初期表示 | 1枚目が表示され、ドットが光る |
| 7 | 切り替え関数を作る | コンソールから手動で切り替わる |
| 8 | 矢印イベントを繋ぐ | 矢印クリックで切り替わる |
| 9 | ドットイベントを繋ぐ | ドットクリックで切り替わる |
| 10 | 連打防止を追加 | 連打しても壊れない |