За словом «слайдер» обычно прячут библиотеку на сто килобайт. Почти всё, ради чего её подключают, современный браузер умеет сам: прокрутку с прилипанием к слайду, плавность и работу пальцем. Своего кода в таком слайдере — десяток строк.
Сначала честный вопрос: нужен ли он
Слайдер прячет содержимое. Из пяти слайдов человек видит один, и до второго доходит меньше половины читателей. Поэтому первый экран сайта каруселью заполнять не стоит: главное сообщение уедет в слайд, до которого никто не долистает.
А вот там, где элементы равнозначны и их много, слайдер на месте: отзывы, фотографии работ, логотипы, карточки товаров. Ни один из них не важнее остальных, и лента экономит высоту страницы.
Проверка одним вопросом
Что случится, если показать все элементы сразу, просто сеткой? Если ответ «ничего плохого, будет длиннее» — берите сетку. Слайдер нужен, когда элементов десятки и сетка из них превращается в простыню.
Разметка: это список, который прокручивается
Никакой особой разметки слайдер не требует. Это обычный список, выложенный в строку: элементы не переносятся, а выходят за край и прокручиваются внутри своей рамки.
<section class="slider" aria-label="Отзывы">
<ul class="slider__track" tabindex="0">
<li class="slider__slide">…</li>
<li class="slider__slide">…</li>
<li class="slider__slide">…</li>
</ul>
<button class="slider__arrow slider__arrow--prev" type="button"
aria-label="Предыдущий слайд">…</button>
<button class="slider__arrow slider__arrow--next" type="button"
aria-label="Следующий слайд">…</button>
</section>
Атрибут tabindex="0" у ленты стоит не для красоты.
Блок с прокруткой обязан быть достижим с клавиатуры: без него
человек, который не пользуется мышью, не сможет пролистать
слайды стрелками. Это требование проверяют автоматические
аудиты доступности, и ругаются они справедливо.
Прокрутка с прилипанием — это три строки CSS
Свойство scroll-snap-type говорит браузеру:
останавливай прокрутку не где попало, а на границах слайдов.
Дальше он сам добавит инерцию, работу пальцем и плавность.
.slider__track {
display: flex;
gap: var(--space-5);
overflow-x: auto;
scroll-snap-type: x mandatory; /* прилипать к слайдам по горизонтали */
scroll-behavior: smooth; /* плавно, а не рывком */
}
.slider__slide {
flex: 0 0 85%; /* на телефоне виден край соседнего */
scroll-snap-align: start;
}
@media (min-width: 768px) {
.slider__slide { flex-basis: calc((100% - var(--space-5) * 2) / 3); }
}
Доля 85% на телефоне — приём, а не случайное
число. Когда из-за края выглядывает кусок следующего слайда,
человеку понятно, что ленту можно листать. Слайд ровно
во всю ширину выглядит как обычная картинка, и половина
читателей просто не догадается её потянуть.
Что добавляет JavaScript
Всё перечисленное работает без единой строки кода. Скрипт нужен только для трёх вещей.
| Что | Как делается |
|---|---|
| Стрелки |
Сдвиг ленты на ширину слайда методом
scrollBy. Кнопка выключается, когда
листать больше некуда
|
| Точки под лентой |
IntersectionObserver следит, какой слайд
сейчас в окне, и подсвечивает нужную точку
|
| Автопрокрутка | Таймер, который двигает ленту сам. Самая спорная возможность — о ней ниже |
Автопрокрутка без трёх условий — вред
Лента обязана останавливаться при наведении курсора
и при попадании фокуса внутрь, рядом должна быть кнопка
«Пауза», и вся затея целиком отключается при системной
настройке «уменьшить движение»
(prefers-reduced-motion). Без этого человек
не успевает дочитать слайд, а у части читателей движущаяся
картинка вызывает физическое недомогание.
Что попросить у нейросети
Просить «сделай слайдер» бесполезно: в ответ приедет библиотека. Просить надо конкретное поведение поверх готовой разметки.
У меня есть слайдер на чистом CSS: лента с
overflow-x: auto и
scroll-snap-type: x mandatory, слайды —
элементы списка. Библиотеки подключать нельзя, сборщика
нет.
Напиши к нему скрипт на чистом JavaScript: две кнопки-стрелки листают ленту ровно на один слайд и становятся неактивными в начале и в конце; под лентой — точки по числу слайдов, текущая подсвечена, щелчок по точке прокручивает к слайду.
Текущий слайд определяй через
IntersectionObserver, а не по позиции
прокрутки. Точки сделай кнопками с понятным текстом для
программ чтения экрана. Если слайды помещаются целиком
и листать нечего, стрелки и точки скрой. Комментарии
по-русски.
Насколько листать. Не берите ширину окна: на планшете видно два с половиной слайда, и лента уедет не туда. Надёжнее взять ширину первого слайда плюс отступ между слайдами — оба значения можно прочитать у реальных элементов.
Про порог наблюдателя. Ставьте
threshold: 0.6. При значении по умолчанию
наблюдатель считает видимыми сразу два соседних слайда,
и подсвеченными оказываются две точки одновременно.
Про пересчёт. Число помещающихся слайдов
меняется при повороте телефона и при изменении размера
окна. Подпишитесь на ResizeObserver
и пересчитывайте видимость стрелок — иначе после поворота
кнопки остаются выключенными, хотя листать уже есть что.
Автопрокрутку я в код не добавлял: вы её не просили,
а без паузы по наведению и учёта
prefers-reduced-motion она делает страницу
хуже.
Слайды из Evolution CMS
В вёрстке слайды написаны руками. В CMS их заводят как обычные
ресурсы в отдельной папке «Слайды» — с картинкой в TV-поле
и заголовком. Выводит их DocLister, а разметку
одного слайда задаёт чанк.
<ul class="slider__track" tabindex="0">
[[DocLister?
&parents=`12`
&tpl=`sliderSlide`
&tvList=`slideImage`
&sortBy=`menuindex`
]]
</ul>
Порядок слайдов задаётся полем «Порядок в меню» — то есть перетаскиванием в дереве ресурсов. Это и есть весь смысл переезда на CMS: поменять слайды местами теперь может человек, который никогда не открывал редактор кода.
Частые ошибки
| Ошибка | Чем плохо | Как правильно |
|---|---|---|
| Главное сообщение в карусели | До второго слайда доходит меньше половины читателей | Важное — обычным блоком, каруселью — равнозначное |
| Библиотека ради прокрутки | Сто килобайт кода вместо трёх строк CSS | scroll-snap-type и scrollBy |
Ленте не поставлен tabindex |
С клавиатуры слайды не пролистать | tabindex="0" на прокручиваемом блоке |
| Стрелки без текста, одни значки | Диктор читает «кнопка», и всё | aria-label с понятным названием |
| Автопрокрутка без паузы | Слайд уезжает недочитанным, движение не остановить | Пауза по наведению и фокусу, кнопка и учёт настройки движения |
Что должно получиться
- Лента листается пальцем, колесом мыши и стрелками клавиатуры
- Прокрутка останавливается ровно на границе слайда
- На телефоне из-за края выглядывает соседний слайд
- Стрелки выключаются в начале и в конце ленты
- Страница не едет вбок: прокручивается лента, а не весь документ