💡 목표
- 외부 라이브러리를 사용하지 않고, 계속해서 반복되는 무한 슬라이더 구현
(마지막 슬라이드에 도달하면 다시 첫번째 슬라이드로) - 자동으로 넘어갈 것
📌 HTML
<div id="sliderWrap">
<ul class="slider">
<li>
<div class="itemWrap"></div>
</li>
<li>
<div class="itemWrap"></div>
</li>
<li>
<div class="itemWrap"></div>
</li>
</ul>
<div id="btn" class="directionNav">
<button id="prev" class="btn">prev</button>
<button id="next" class="btn">next</button>
</div>
<ul class="dot">
<li class="dots on">btn01</li>
<li class="dots">btn02</li>
<li class="dots">btn03</li>
</ul>
</div>
📌 CSS
/* reset */
li { list-style: none; }
button { border: none; }
div, ul, li, button { margin: 0; padding: 0; }
#sliderWrap { position: relative; width: 300px; height: 200px; overflow: hidden; }
/* slide item */
#sliderWrap .slider { position: absolute; top: 0; left: 0; height: 100%;}
#sliderWrap .slider li { float: left; position: relative; top: 0; left: 0; height: 100%; }
#sliderWrap .slider li .itemWrap { width: 100%; height: 100%; text-align: center; }
/* item background color */
#sliderWrap .slider li:nth-child(1) .itemWrap { background-color: #ff8181; }
#sliderWrap .slider li:nth-child(2) .itemWrap { background-color: #fff281; }
#sliderWrap .slider li:nth-child(3) .itemWrap { background-color: #81d1ff; }
/* button */
#sliderWrap .directionNav { position: relative; width: 100%; height: 100%; }
#sliderWrap .directionNav button { position: absolute; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; font-size: 0; background: none; cursor: pointer; }
#sliderWrap .directionNav button::after { display: block; content: ""; width: 100%; height: 100%; border-right: 3px solid #000; border-top: 3px solid #000; transform: rotate(45deg); opacity: 0.6; }
#sliderWrap .directionNav button#prev { left: 20px; }
#sliderWrap .directionNav button#prev::after { transform: rotate(-135deg); }
#sliderWrap .directionNav button#next { right: 20px; }
/* pagination */
.dot { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); }
.dot li { float: left; width: 10px; height: 10px; margin: 0 4px; border-radius: 50px; background: #000; opacity: 0.3; text-indent: -9999px; cursor: pointer; }
.dot li.on { opacity: 1; }
📌 JavaScript
function initializeSlider() {
const slideWrapper = document.getElementById('sliderWrap');
const slider = document.querySelector('#sliderWrap .slider');
const slides = document.querySelectorAll('#sliderWrap .slider li');
const sliderWidth = slideWrapper.clientWidth;
const totalSlides = slides.length;
let slideIndex = 0;
let autoSlider;
// Set slide widths
slides.forEach(function (element) {
element.style.width = sliderWidth + 'px';
});
slider.style.width = sliderWidth * totalSlides + 'px';
// Next, Prev, Pagination
const nextBtn = document.getElementById('next');
const prevBtn = document.getElementById('prev');
const dot = document.querySelector('.dot');
const allBtn = document.getElementById('btn');
function plusSlides(n) {
showSlides(slideIndex + n);
}
function showSlides(n) {
slideIndex = (n + totalSlides) % totalSlides;
slider.style.left = -(sliderWidth * slideIndex) + 'px';
pagination();
}
function currentSlides(n) {
showSlides(n);
}
function pagination() {
const dots = document.querySelectorAll('.dot li');
dots.forEach(function (element) {
element.classList.remove('on');
});
dots[slideIndex].classList.add('on');
}
// Handle dot clicks
dot.addEventListener('click', function (event) {
if (event.target.tagName === 'LI') {
showSlides(Array.from(event.target.parentNode.children).indexOf(event.target));
}
});
// Handle button clicks
nextBtn.addEventListener('click', function () {
plusSlides(1);
});
prevBtn.addEventListener('click', function () {
plusSlides(-1);
});
// Handle hover
const hoverElements = [allBtn, dot];
hoverElements.forEach(function (element) {
element.addEventListener('mouseover', function () {
this.classList.add('active');
clearInterval(autoSlider);
});
element.addEventListener('mouseleave', function () {
this.classList.remove('active');
startAutoSlider();
});
});
// Auto slider
function startAutoSlider() {
autoSlider = setInterval(function () {
plusSlides(1);
}, 3000);
}
// Initialize auto slider
startAutoSlider();
}
// 호출하여 슬라이더 초기화
initializeSlider();
💛 결과물
728x90
반응형
'퍼블리싱 > Vanilla JS' 카테고리의 다른 글
[Vanilla JS] 스와이퍼 없이 슬라이더 구현하기 (+ play/stop/progress bar) (0) | 2024.05.28 |
---|---|
[Vanilla JS] 숫자 상승 애니메이션 / 카운트 애니메이션 (0) | 2023.10.27 |
[Vanilla JS] 스크롤 이벤트 구현 Scroll Event (1) | 2023.10.27 |
[Vanilla JS] 무한루프 슬라이더 구현 (1) | 2023.10.27 |
[Vanilla JS] 탭 메뉴 구현 / 버튼마다 다른 컨텐츠 보여주기 (0) | 2023.10.27 |