UnsplashのClaudio Testaが撮影した写真
CSSとJavaScriptでカルーセルを作成したのでコードの紹介です。
SassやjQueryなどを使っていないので、このコードをベースに自由にカスタムしていただけるかと思います。
以下のHTML、CSS、JavaScriptをそれぞれのファイルに分け、以下の3ファイルで作成しています。
・carousel.html
・carousel.css
・carousel.js
上の3つのファイルを作成し、それぞれに以降のコードをコピペすると動きます。
<html>
<head>
<!-- CSSの読み込み -->
<link rel="stylesheet" type="text/css" href="./carousel.css">
</head>
<body>
<div class="carousel">
<!-- 画像表示部分 -->
<div id="items-wrapper">
<img class="active" src="https://tekutekku.com/wp-content/uploads/2023/10/231026_1.jpg">
<img src="https://tekutekku.com/wp-content/uploads/2023/10/231026_1.jpg">
<img src="https://tekutekku.com/wp-content/uploads/2023/10/231026_1.jpg">
</div>
<!-- 画像をタブで切り替えるボタン -->
<div id="select-tabs">
<button class="active" onclick="changeToSelectItem(0)"></button>
<button onclick="changeToSelectItem(1)"></button>
<button onclick="changeToSelectItem(2)"></button>
</div>
<!-- 隣の画像に移動するボタン -->
<div id="change-buttons">
<button onclick="changeToPrevItem()"></button>
<button onclick="changeToNextItem()"></button>
</div>
</div>
<!-- JavaScriptの読み込み -->
<script src="./carousel.js"></script>
</body>
</html>
/* カルーセル/////////////////////////// */
.carousel{
margin: 0 auto;
--carousel-width: 420px;
--carousel-height: 240px;
width: var(--carousel-width);
height: var(--carousel-height);
position: relative;
}
/* items----------------------------------- */
.carousel #items-wrapper{
margin: 0 auto;
width: calc(var(--carousel-width) - 100px);
height: var(--carousel-height);
position: relative;
overflow: hidden;
}
.carousel #items-wrapper img{
width: 100%;
position: absolute;
top: 20%;
left: 0;
opacity: 0;
}
.carousel #items-wrapper img.active{
opacity: 1;
}
.carousel #items-wrapper img.fadeRightIn{
animation-name: fadeRightIn;
animation-duration: 1s;
opacity: 1;
}
.carousel #items-wrapper img.fadeLeftOut{
animation-name: fadeLeftOut;
animation-duration: 1s;
}
.carousel #items-wrapper img.fadeLeftIn{
animation-name: fadeLeftIn;
animation-duration: 1s;
opacity: 1;
}
.carousel #items-wrapper img.fadeRightOut{
animation-name: fadeRightOut;
animation-duration: 1s;
}
@keyframes fadeRightIn {
0% {
opacity: 0;
transform: translateX(100%);
}
100% {
opacity: 1;
transform: translateX(0%);
}
}
@keyframes fadeLeftOut{
0% {
opacity: 1;
transform: translateX(0%);
}
100% {
opacity: 0;
transform: translateX(-100%);
}
}
@keyframes fadeLeftIn {
0% {
opacity: 0;
transform: translateX(-100%);
}
100% {
opacity: 1;
transform: translateX(0%);
}
}
@keyframes fadeRightOut{
0% {
opacity: 1;
transform: translateX(0%);
}
100% {
opacity: 0;
transform: translateX(100%);
}
}
/* select-tabs----------------------------- */
#select-tabs{
width: var(--carousel-width);
text-align: center;
position: absolute;
top: 90%;
left: 0;
}
#select-tabs button{
margin: 0 3px;
width: 20px;
height: 20px;
background-color: #ccc;
border-radius: 50%;
border: none;
cursor: pointer;
}
#select-tabs button.active{
background-color: #888;
}
/* change-buttons-------------------------- */
#change-buttons{
width: var(--carousel-width);
display: flex;
justify-content: space-between;
position: absolute;
top: 45%;
left: 0;
}
#change-buttons button{
width: 36px;
height: 36px;
border: none;
border-radius: 50%;
cursor: pointer;
position: relative;
--arrow-size: 10px;
--arrow-design: 3px solid black;
--arrow-rotate: -45deg;
display: flex;
justify-content: center;
align-items: center;
}
/* 前へボタン */
#change-buttons button:nth-child(1)::after{
content: "";
width: var(--arrow-size);
height: var(--arrow-size);
display: block;
border-top: var(--arrow-design);
border-left: var(--arrow-design);
transform: rotate(var(--arrow-rotate));
}
/* 次へボタン */
#change-buttons button:nth-child(2)::after{
content: "";
width: var(--arrow-size);
height: var(--arrow-size);
display: block;
border-bottom: var(--arrow-design);
border-right: var(--arrow-design);
transform: rotate(var(--arrow-rotate));
}
//itemを自動で切り替える間隔(ミリ秒で指定)
let intervalTime = 3000;
//////////////////////////////////////////////////////////////////////////////////
// ↓↓ 以降のコードは触らない ↓↓ //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//事前準備
let itemElements = document.getElementById('items-wrapper'); //以降の処理で使いまわすので事前に要素を取得しておく
let tabElements = document.getElementById('select-tabs'); //以降の処理で使いまわすので事前に要素を取得しておく
let itemNum = itemElements.childElementCount - 1; //インデックスは0スタートなので、取得した要素数から1引く
let activeNum = 0; //アクティブなitemの番号を格納
let intervalId = setInterval(changeToNextItem, intervalTime); //itemの自動切り替え
//■以降の処理で使いまわす関数
//select-tab,change-buttonが押された時に、自動切り替えのタイマーをリセットする
function resetInterval(){
clearInterval(intervalId);
intervalId = setInterval(changeToNextItem, intervalTime);
}
//itemの切り替えに伴うtabの切り替え処理
function changeActiveTab(fromActiveNum, toActiveNum){
fromTab = tabElements.children[fromActiveNum];
fromTab.classList.remove('active');
toTab = tabElements.children[toActiveNum];
toTab.classList.add('active');
}
// select-tabsでのitemの切り替え処理 ---------------------------
function changeToSelectItem(i){
resetInterval();
fromActiveNum = activeNum;
toActiveNum = i;
//アクティブなitemが選択されたら何もせず処理を終了する
if(fromActiveNum == toActiveNum){return;}
fromItem = itemElements.children[fromActiveNum];
fromItem.classList.remove('active');
fromItem.classList.remove('fadeRightIn');
fromItem.classList.remove('fadeLeftIn');
toItem = itemElements.children[toActiveNum];
toItem.classList.remove('fadeLeftOut');
toItem.classList.remove('fadeRightOut');
if(activeNum < toActiveNum){
//次のスライドへ移動する時
fromItem.classList.add('fadeLeftOut')
toItem.classList.add('fadeRightIn');
}else{
//前のスライドへ移動する時
fromItem.classList.add('fadeRightOut')
toItem.classList.add('fadeLeftIn');
}
changeActiveTab(fromActiveNum, toActiveNum)
activeNum = toActiveNum;
}
// change-buttonでのitemの切り替え処理 ---------------------
function changeToPrevItem(){
resetInterval();
fromActiveNum = activeNum;
fromItem = itemElements.children[activeNum];
fromItem.classList.remove('active');
fromItem.classList.remove('fadeRightIn');
fromItem.classList.remove('fadeLeftIn');
if(activeNum == 0){
activeNum = itemNum;
}else{
--activeNum;
}
toActiveNum = activeNum;
toItem = itemElements.children[activeNum];
toItem.classList.remove('fadeLeftOut');
toItem.classList.remove('fadeRightOut');
fromItem.classList.add('fadeRightOut')
toItem.classList.add('fadeLeftIn');
toItem.classList.add('active');
changeActiveTab(fromActiveNum, toActiveNum)
}
function changeToNextItem(){
resetInterval();
fromActiveNum = activeNum;
fromItem = itemElements.children[activeNum];
fromItem.classList.remove('active');
fromItem.classList.remove('fadeRightIn');
fromItem.classList.remove('fadeLeftIn');
if(activeNum == itemNum){
activeNum = 0;
}else{
++activeNum;
}
toActiveNum = activeNum;
toItem = itemElements.children[activeNum];
toItem.classList.remove('fadeLeftOut');
toItem.classList.remove('fadeRightOut');
fromItem.classList.add('fadeLeftOut')
toItem.classList.add('fadeRightIn');
toItem.classList.add('active');
changeActiveTab(fromActiveNum, toActiveNum)
}