За словом «слайдер» обычно прячут библиотеку на сто килобайт. Почти всё, ради чего её подключают, современный браузер умеет сам: прокрутку с прилипанием к слайду, плавность и работу пальцем. Своего кода в таком слайдере — десяток строк.

Сначала честный вопрос: нужен ли он

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

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

Проверка одним вопросом

Что случится, если показать все элементы сразу, просто сеткой? Если ответ «ничего плохого, будет длиннее» — берите сетку. Слайдер нужен, когда элементов десятки и сетка из них превращается в простыню.

Разметка: это список, который прокручивается

Никакой особой разметки слайдер не требует. Это обычный список, выложенный в строку: элементы не переносятся, а выходят за край и прокручиваются внутри своей рамки.

Разметка ленты
<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 с понятным названием
Автопрокрутка без паузы Слайд уезжает недочитанным, движение не остановить Пауза по наведению и фокусу, кнопка и учёт настройки движения

Что должно получиться

  • Лента листается пальцем, колесом мыши и стрелками клавиатуры
  • Прокрутка останавливается ровно на границе слайда
  • На телефоне из-за края выглядывает соседний слайд
  • Стрелки выключаются в начале и в конце ленты
  • Страница не едет вбок: прокручивается лента, а не весь документ