Слайдер для сайта: как сделать на CSS, JS и через библиотеки

Слайдер для сайта: как сделать на CSS, JS и через библиотеки Полезное

Слайдер — это блок на странице, который по очереди показывает набор слайдов (изображений, карточек или текстовых блоков), переключая их по кнопкам, точкам-индикаторам, свайпу или по таймеру. Задача слайдера — уместить несколько сообщений в одну область экрана.

В этой статье разберу, чем слайдер отличается от карусели, когда его стоит ставить, а когда лучше обойтись без него, и сделаю рабочий слайдер тремя способами: на чистом CSS через scroll-snap, вручную на JavaScript и через готовую библиотеку Swiper. Каждый пример можно скопировать и запустить.

Слайдер и карусель: в чем разница

Слова «слайдер» и «карусель» в вебе часто используют как синонимы, и строгого стандарта тут нет. Но на практике сложилось удобное разделение, которое помогает выбрать реализацию.

  • Слайдер обычно показывает один крупный слайд за раз и меняет их целиком (частый случай — баннер-герой в шапке).
  • Карусель обычно показывает несколько элементов в ряд и прокручивает их вбок по одному (карточки товаров, логотипы партнеров, отзывы).

Это соглашение, а не жесткое правило: одна и та же библиотека делает оба варианта, отличается лишь настройка «сколько слайдов видно за раз». Дальше под словом «слайдер» я буду иметь в виду любой из этих вариантов.

Когда слайдер нужен, а когда лучше без него

Слайдер экономит место, но у него есть цена: контент во втором и следующих слайдах пользователь видит не сразу, а иногда не видит вовсе. Поэтому решать стоит по задаче, а не по моде.

Слайдер уместен, когда элементы равнозначны и их не обязательно смотреть все сразу: галерея фотографий товара, отзывы, логотипы, подборка карточек в ленте.

Слайдер лучше не использовать для ключевых сообщений и призывов к действию. Если важный оффер лежит на третьем слайде, до него доходит мало кто. В таких случаях надежнее показать главное статично, а второстепенное вынести ниже по странице.

Отдельно про автопрокрутку: по наблюдениям юзабилити-исследований, дальше первого слайда автопереключаемого баннера доходит небольшая доля пользователей, а движение мешает читать. Если автопрокрутка нужна, обязательно давайте паузу при наведении и учитывайте системную настройку «уменьшить движение».

Слайдер на чистом CSS (scroll-snap)

Самый простой слайдер вообще не требует JavaScript. Современный CSS умеет «прилипать» к слайдам при прокрутке через свойство scroll-snap. Такой слайдер листается свайпом на телефоне и колесом или трекпадом на десктопе, а весит буквально ничего.

Разметка — контейнер и слайды внутри:

<div class="slider">
  <div class="slider__item"><img src="1.jpg" alt="Первый слайд"></div>
  <div class="slider__item"><img src="2.jpg" alt="Второй слайд"></div>
  <div class="slider__item"><img src="3.jpg" alt="Третий слайд"></div>
</div>

Стили: раскладываем слайды в строку, включаем горизонтальную прокрутку и точки прилипания.

.slider {
  display: flex;
  overflow-x: auto;              /* горизонтальная прокрутка */
  scroll-snap-type: x mandatory; /* прилипание по оси X */
  scroll-behavior: smooth;       /* плавная прокрутка */
  width: 600px;
  max-width: 100%;
  aspect-ratio: 3 / 2;           /* фиксируем пропорции, чтобы не прыгал макет */
}

.slider__item {
  flex: 0 0 100%;                /* каждый слайд шириной с контейнер */
  scroll-snap-align: start;      /* точка прилипания - у начала слайда */
}

.slider__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Что здесь происходит: scroll-snap-type: x mandatory заставляет контейнер после прокрутки останавливаться ровно на слайде, а scroll-snap-align: start задает, какой точкой слайд выравнивается. flex: 0 0 100% не дает слайдам сжиматься, поэтому в видимой области всегда один слайд.

Свойство scroll-snap поддерживают все актуальные браузеры (Chrome, Firefox, Safari, Edge). Минус подхода — нет готовых кнопок «вперед/назад» и точек-индикаторов, только сама прокрутка. Если кнопки нужны, добавляем немного JavaScript.

Слайдер на JavaScript вручную

Ручной слайдер на JavaScript дает полный контроль: кнопки, зацикливание, автопрокрутка. Разберу минимальный, но рабочий вариант с двумя кнопками.

Разметка: дорожка со слайдами и две кнопки. Кнопки делаю настоящими элементами <button> с понятной подписью для скринридеров.

<div class="slider">
  <div class="slider__track">
    <img src="1.jpg" alt="Первый слайд">
    <img src="2.jpg" alt="Второй слайд">
    <img src="3.jpg" alt="Третий слайд">
  </div>
  <button class="slider__prev" aria-label="Предыдущий слайд"></button>
  <button class="slider__next" aria-label="Следующий слайд"></button>
</div>

Стили: контейнер прячет все, что вне видимой области, дорожка сдвигается по горизонтали с анимацией.

.slider {
  position: relative;
  width: 600px;
  max-width: 100%;
  overflow: hidden;
  margin: 0 auto;
}

.slider__track {
  display: flex;
  transition: transform 0.4s ease-in-out; /* плавный сдвиг */
}

.slider__track img {
  flex: 0 0 100%; /* один слайд на всю ширину */
  width: 100%;
  display: block;
}

.slider__prev,
.slider__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  border: none;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 24px;
  cursor: pointer;
}

.slider__prev { left: 8px; }
.slider__next { right: 8px; }

Логика на JavaScript: храним индекс текущего слайда и сдвигаем дорожку через transform: translateX. Ключевая деталь — зацикливание по остатку от деления, чтобы после последнего слайда показывался первый, а не пустота.

const track = document.querySelector('.slider__track');
const prev = document.querySelector('.slider__prev');
const next = document.querySelector('.slider__next');
const total = track.children.length;
let index = 0;

function show(i) {
  index = (i + total) % total;                       // всегда держим индекс в диапазоне 0..total-1
  track.style.transform = `translateX(${-index * 100}%)`;
}

prev.addEventListener('click', () => show(index - 1));
next.addEventListener('click', () => show(index + 1));

show(0); // показываем первый слайд при загрузке

Самое хрупкое место новичка — переход через край: с последнего слайда «вперед» и с первого «назад». Его решает выражение (i + total) % total. Проверю эту логику отдельным самодостаточным кодом, без DOM, чтобы увидеть числа:

const total = 3;
let index = 0;
const step = (i) => (i + total) % total;

index = step(index + 1); // вперед с 0
console.log(index);      // 1
index = step(index + 1);
console.log(index);      // 2
index = step(index + 1); // с последнего - снова на первый
console.log(index);      // 0
index = step(index - 1); // назад с 0 - на последний
console.log(index);      // 2

В консоли последовательно появится 1, 2, 0, 2. Видно, что индекс не выходит за границы и корректно перескакивает через край в обе стороны. Именно эту функцию show и вызывает по клику.

Чтобы добавить автопрокрутку, достаточно вызвать setInterval(() => show(index + 1), 4000). Но тогда добавьте паузу по наведению (mouseenter/mouseleave) и не запускайте движение при системной настройке «уменьшить движение».

Готовые библиотеки: Swiper и альтернативы

Если нужен слайдер со свайпами, эффектами, вложенными слайдерами и адаптивными точками остановки, писать это вручную долго и легко ошибиться. Проще взять готовую библиотеку.

Ориентир по выбору — зависимости и размер. Современные библиотеки не требуют jQuery; наоборот, слайдеры на jQuery сегодня относятся к legacy и для новых проектов их брать не стоит.

Библиотека Зависимости Когда брать
Swiper нет функциональные слайдеры: тач, свайпы, эффекты, вложенность; де-факто стандарт
Splide нет легковесная альтернатива Swiper с аккуратной поддержкой доступности
Glide.js нет минималистичный слайдер, когда важен маленький вес
Slick, Owl Carousel jQuery только legacy-проекты, уже построенные на jQuery

Чаще всего берут Swiper — библиотеку без зависимостей, которая работает и в чистом HTML, и внутри React, Vue или Angular. Ставится через менеджер пакетов:

npm install swiper

Разметка Swiper построена на обертке и слайдах с определенными классами:

<div class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">Слайд 1</div>
    <div class="swiper-slide">Слайд 2</div>
    <div class="swiper-slide">Слайд 3</div>
  </div>
</div>

Инициализация в JavaScript — импортируем библиотеку и ее стили, затем создаем экземпляр:

import Swiper from 'swiper';
import 'swiper/css';

const swiper = new Swiper('.swiper', {
  loop: true,        // бесконечная прокрутка
  slidesPerView: 1,  // сколько слайдов видно за раз
  spaceBetween: 16,  // отступ между слайдами, px
});

Чтобы из слайдера (один крупный слайд) получить карусель (несколько карточек в ряд), достаточно увеличить slidesPerView, например до 3, и при желании задать разное число слайдов для разной ширины экрана через параметр breakpoints. Кнопки, точки-индикаторы и автопрокрутку Swiper добавляет своими модулями — это описано в его документации.

Подключить Swiper можно не только через npm, но и с публичного CDN (например jsDelivr или unpkg) — тогда файлы библиотеки берутся готовой сборкой без установки.

Доступность и производительность

Слайдер легко сделать красивым, но неудобным. Несколько правил, которые отличают аккуратную реализацию.

По доступности:

  • Кнопки управления — настоящие <button> с атрибутом aria-label, а не <div> с обработчиком клика. Так слайдер работает с клавиатуры и со скринридером.
  • Уважайте настройку prefers-reduced-motion: при ней отключайте автопрокрутку и резкие анимации.
  • Не прячьте в дальние слайды важный контент и призывы к действию — их могут не увидеть ни пользователь, ни поисковый робот.

По производительности:

  • Первому слайду оставляйте обычную загрузку, а картинкам дальних слайдов ставьте loading="lazy" — тогда они не тормозят первую отрисовку.
  • Фиксируйте пропорции контейнера (aspect-ratio или заданные размеры), чтобы при загрузке не прыгал макет (сдвиг макета вредит и удобству, и метрикам Core Web Vitals).
  • Не подключайте тяжелую библиотеку ради одного слайда: для простого случая хватит подхода на чистом CSS.

Выводы

  • Слайдер по очереди показывает набор слайдов; «карусель» — его частный случай с несколькими видимыми элементами (разделение условное).
  • Ставьте слайдер для равнозначного контента, а ключевые сообщения показывайте статично.
  • Простейший рабочий слайдер делается на чистом CSS через scroll-snap, без единой строки JavaScript.
  • Ручной слайдер на JavaScript дает кнопки и зацикливание; переход через край решает выражение (i + total) % total.
  • Для сложных случаев берите современную библиотеку без зависимостей (Swiper, Splide, Glide.js); слайдеры на jQuery устарели.

Где применяется и как учиться дальше

Слайдеры и карусели — повседневный элемент фронтенда: баннеры на главной, галереи товаров, блоки отзывов и логотипов, подборки статей. Разработчику интерфейсов важно уметь и собрать такой блок вручную, и подключить готовую библиотеку, и не сломать при этом доступность и скорость загрузки.

Освойте тему на практике

Освоить верстку и поведение таких компонентов системно, с практикой и разбором кода, удобнее на курсе. Хорошая точка входа для новичка — HTML и CSS: курс по разработке сайтов для начинающих, где как раз учат собирать интерфейсные блоки страницы. А чтобы посмотреть формат занятий и разобрать тему вживую с преподавателем, загляните на открытые уроки и вебинары Otus.

Смежные темы: Float в CSS, Селекторы CSS, Условный оператор if в JavaScript.

FAQ

Нужен ли jQuery, чтобы сделать слайдер?
Нет. Современные библиотеки (Swiper, Splide, Glide.js) работают без него, а простой слайдер собирается вообще на чистом CSS. jQuery-слайдеры вроде Slick и Owl Carousel — это legacy, для новых проектов их брать не стоит.

Сколько слайдов делать?
Немного: обычно 3-5. Чем больше слайдов, тем меньше шансов, что пользователь досмотрит до конца, и тем больше данных грузится. Если элементов много, лучше показать их списком или сеткой.

Слайдер вредит SEO?
Текст и ссылки внутри слайдов индексируются, если они есть в разметке страницы. Риск в другом: важные сообщения на дальних слайдах реже попадают в поле зрения, а контент, который подгружается только по действию пользователя, робот может не увидеть. Ключевое выносите за пределы слайдера.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)