Создание слайдера на чистом JavaScript — это не просто практическое упражнение, но и отличный способ глубоко понять, как работает манипуляция DOM, обработка событий и CSS-анимации. В этой статье мы шаг за шагом построим полнофункциональный, плавный и адаптивный слайдер изображений, не прибегая к помощи jQuery, Swiper или других библиотек. Вы получите не только рабочий код, но и фундаментальное понимание процессов.
Зачем создавать слайдер самостоятельно?
В эпоху готовых решений закономерен вопрос: зачем изобретать велосипед? Ответ прост: контроль, производительность и обучение. Самописный слайдер будет весить в разы меньше, чем подключаемая библиотека, он будет делать ровно то, что нужно вашему проекту, без избыточного функционала. Но главное — этот процесс прокачивает ваши навыки работы с нативным JS.
Ключевой принцип: В основе любого слайдера лежит массив элементов (слайдов) и индекс текущего активного элемента. Вся логика — это изменение этого индекса и визуальное обновление контейнера.
Шаг 1: Базовая HTML-разметка
Начнем с семантической и доступной структуры. Нам понадобится контейнер для слайдов, сами слайды (в нашем случае — изображения) и элементы управления.
Код разметки
<div class="slider" role="region" aria-label="Галерея изображений">
<div class="slider__track-container">
<div class="slider__track">
<div class="slider__slide"><img src="img1.jpg" alt="Описание 1"></div>
<div class="slider__slide"><img src="img2.jpg" alt="Описание 2"></div>
<div class="slider__slide"><img src="img3.jpg" alt="Описание 3"></div>
</div>
</div>
<button class="slider__btn slider__btn--prev" aria-label="Предыдущий слайд"><</button>
<button class="slider__btn slider__btn--next" aria-label="Следующий слайд">></button>
<div class="slider__nav"></div>
</div>
Шаг 2: Стилизация на CSS
CSS обеспечит базовое расположение и скроет неактивные слайды. Мы используем Flexbox или CSS Grid для выравнивания и трансформации для анимации.
Ключевые стили
.slider {
position: relative;
overflow: hidden;
max-width: 800px;
margin: 0 auto;
}
.slider__track {
display: flex;
transition: transform 0.5s ease-in-out;
}
.slider__slide {
min-width: 100%;
box-sizing: border-box;
}
.slider__slide img {
width: 100%;
height: auto;
display: block;
}
.slider__btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
color: white;
border: none;
padding: 1rem;
cursor: pointer;
z-index: 10;
}
.slider__btn--prev { left: 0; }
.slider__btn--next { right: 0; }
.slider__nav {
display: flex;
justify-content: center;
padding: 1rem 0;
}
Шаг 3: JavaScript: Оживляем слайдер
Теперь самое интересное — логика на JavaScript. Мы реализуем переключение по стрелкам, навигацию по точкам, бесконечную прокрутку и адаптацию к касаниям (touch events).
Инициализация и переменные
class SimpleSlider {
constructor(containerSelector) {
this.slider = document.querySelector(containerSelector);
this.track = this.slider.querySelector('.slider__track');
this.slides = Array.from(this.track.children);
this.nextBtn = this.slider.querySelector('.slider__btn--next');
this.prevBtn = this.slider.querySelector('.slider__btn--prev');
this.navContainer = this.slider.querySelector('.slider__nav');
this.currentIndex = 0;
this.slideSize = this.slides[0].getBoundingClientRect().width;
this.init();
}
init() {
this.setSlidePosition();
this.createDots();
this.addEventListeners();
window.addEventListener('resize', () => this.handleResize());
}
setSlidePosition() {
this.slideSize = this.slides[0].getBoundingClientRect().width;
this.slides.forEach((slide, index) => {
slide.style.left = this.slideSize * index + 'px';
});
this.moveToSlide(this.currentIndex);
}
moveToSlide(index) {
this.track.style.transform = `translateX(-${this.slideSize * index}px)`;
this.currentIndex = index;
this.updateDots();
}
nextSlide() {
let newIndex = this.currentIndex + 1;
if (newIndex >= this.slides.length) newIndex = 0; // Для бесконечного цикла можно изменить логику
this.moveToSlide(newIndex);
}
prevSlide() {
let newIndex = this.currentIndex - 1;
if (newIndex < 0) newIndex = this.slides.length - 1;
this.moveToSlide(newIndex);
}
createDots() {
this.slides.forEach((_, index) => {
const dot = document.createElement('button');
dot.classList.add('slider__dot');
dot.setAttribute('aria-label', `Перейти к слайду ${index + 1}`);
dot.addEventListener('click', () => this.moveToSlide(index));
this.navContainer.appendChild(dot);
});
this.updateDots();
}
updateDots() {
const dots = this.navContainer.querySelectorAll('.slider__dot');
dots.forEach((dot, index) => {
dot.classList.toggle('slider__dot--active', index === this.currentIndex);
});
}
addEventListeners() {
this.nextBtn.addEventListener('click', () => this.nextSlide());
this.prevBtn.addEventListener('click', () => this.prevSlide());
// Добавьте здесь обработчики для touch событий (touchstart, touchmove, touchend)
}
handleResize() {
this.setSlidePosition(); // Пересчитываем позиции при изменении размера окна
}
}
// Инициализация слайдера
const mySlider = new SimpleSlider('.slider');
Производительность: Для анимации используйте CSS-свойство `transform` вместо `left`/`margin`. Оно обрабатывается графическим процессором (GPU) и обеспечивает плавность даже на слабых устройствах.
Шаг 4: Доработки и улучшения
Базовый слайдер готов. Но его можно значительно улучшить:
- Бесконечная прокрутка: Клонируйте первый и последний слайды и корректно обрабатывайте переходы.
- Автопрокрутка: Добавьте `setInterval` для автоматической смены слайдов с паузой при наведении.
- Touch-события: Реализуйте поддержку свайпов на мобильных устройствах, отслеживая `touchstart`, `touchmove`, `touchend`.
- Ленивая загрузка (Lazy Load): Загружайте изображения только когда они попадают в область видимости.
- Доступность (A11y): Управление с клавиатуры (Tab, стрелки), правильные ARIA-атрибуты, скрытие невидимых слайдов от скринридеров.
FAQ: Часто задаваемые вопросы
Сложно ли сделать слайдер на чистом JS?
Нет, если разбить задачу на этапы: разметка, стили, базовая логика переключения, добавление дополнительных функций. Эта статья — готовый план.
Чем самописный слайдер лучше готовой библиотеки?
Меньший вес (иногда в 10-20 раз), полный контроль над функционалом и анимациями, отсутствие зависимостей, ценный опыт отладки собственного кода.
Как добавить плавную анимацию перехода?
Используйте CSS-переход (`transition`) для свойства `transform` у элемента `.slider__track`. Длительность и функция easing настраиваются в CSS.
Как реализовать адаптивность слайдера?
Слайдер уже адаптивен, если ширина слайда задана как 100% от контейнера. В методе `handleResize()` мы пересчитываем позиции при изменении размера окна.
Можно ли делать слайдер не только для изображений?
Конечно! Внутри `.slider__slide` может быть любой HTML-контент: текст, видео, карточки товаров, отзывы. Принцип работы от этого не меняется.