Перейти к содержимому
Поиск
Разработка

Swiper: слайдеры и карусели — 8 интерфейсов и мастерская

Восемь работающих интерфейсов на Swiper: каталог, галерея, знакомство, отзывы, свободная лента, стопка карточек, Virtual и вертикальные обновления. Настройки и скачиваемые исходники.

Александр Некрасов
Swiper — карусели и слайдеры для интерфейсов, карточки и навигация

В карточке товара человек хочет посмотреть цвет и детали. В каталоге — быстро сравнить несколько вариантов. После регистрации — понять, с чего начать. На странице проекта — прочитать отзывы, не продираясь через длинную простыню. Во всех этих ситуациях пригодится карусель, но задача у неё разная: показать выбор, объяснить последовательность, дать рассмотреть изображение или аккуратно разместить дополнительный материал.

Swiper помогает собрать такие интерфейсы на обычном JavaScript. Здесь восемь живых сценариев, настройки, кнопки, клавиатурная навигация и готовые исходники. Можно увеличить иллюстрацию, собрать учебную подборку, пройти знакомство с сервисом и прыгнуть к карточке 150 в виртуальной ленте. Разберём, как это устроено, когда слайдер полезен, какие настройки мешают пользователю и как разместить готовую мастерскую на Linux-сервере. В проекте зафиксированы Swiper 14.4.0 и Bootstrap 5.3.8.

Что такое Swiper и за какую часть интерфейса он отвечает

Swiper — JavaScript-библиотека для слайдеров и каруселей. Она рассчитывает положение слайдов, обрабатывает перемещение, поддерживает адаптивное количество карточек, навигацию, пагинацию, эффекты и дополнительные модули. Описание товара, кнопка выбора, заголовок, цена и ваши бизнес-действия остаются обычным HTML. Поэтому библиотеку можно использовать в статической странице, шаблоне PHP, личном кабинете или приложении с собственным API.

Практический результат — управляемая область, в которой пользователь понимает, что сейчас показано и куда двигаться дальше. У карточек может быть одинаковая или разная ширина. Крупная галерея умеет синхронизироваться с миниатюрами. Большой список может хранить данные целиком, но держать в DOM только соседние элементы. При этом Swiper не оформляет заказ, не сохраняет профиль и не заменяет серверную проверку данных: такие действия вы подключаете отдельно.

Для статьи используется обычная браузерная версия. Сборка не требует React или Vue, а готовые файлы можно подключить к существующему Bootstrap-сайту. Это удобно, когда нужно улучшить конкретный блок без замены всего проекта. Официальная документация описывает также другие варианты интеграции; здесь мы последовательно работаем с одним вариантом, чтобы исходники можно было сразу повторить.

Где слайдер помогает, а где удобнее обычная сетка

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

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

Хорошая проверка перед разработкой проста: сформулируйте действие после просмотра. Выбрать товар, изучить деталь, прочитать следующий совет, завершить знакомство — понятные результаты. Если единственный ответ «пусть на странице что-нибудь движется», сначала стоит переработать содержание. В мастерской каждый вариант сопровождается описанием применения и конкретным действием, которое можно выполнить прямо сейчас.

Мини-мастерская: восемь интерфейсов с настоящим поведением

Выберите сценарий в верхнем списке. Настройка скорости меняет длительность перехода, расстояние — промежуток между карточками там, где это имеет смысл. Режим по кругу доступен каталогу. Изменение настройки пересоздаёт текущий пример и очищает локальное состояние: подборка, текущий слайд и прохождение знакомства начинаются заново. Для повторного эксперимента есть отдельная кнопка сброса.

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

Под примером находятся кнопки копирования и скачивания HTML. Полученный файл содержит тот же renderer, набор данных и выбранные настройки. Для работы ему нужны локальные vendor-файлы из полного архива. Благодаря этому можно сначала настроить вариант на странице, затем положить его в свой проект и заменить тексты, изображения и действия.

Версия, лицензия и состав скачиваемого проекта

На момент подготовки материала актуальная стабильная версия Swiper — 14.4.0, опубликованная 30 октября 2026 года. Она закреплена в package.json без диапазона и в package-lock.json. Сборка копирует локальные CSS и JavaScript в public/vendor; посетитель страницы не зависит от внешнего CDN. Обновлять библиотеку можно позже осознанно, после проверки собственных сценариев. Изменение номера в документации само по себе не обновляет уже скачанный проект.

Swiper распространяется по MIT. Авторский код мастерской и учебные SVG тоже доступны под MIT; лицензии Swiper и Bootstrap сохранены рядом с исходниками. Платные шаблоны, на которые можно встретить ссылки на сайте библиотеки, в архив не входят. Все восемь интерфейсов собраны здесь из открытых возможностей библиотеки и обычной разметки.

В каталоге src лежат данные, функция создания интерфейса, стили и генератор примера. Каталог public уже готов к размещению. Локальный сервер нужен для удобного просмотра через HTTP, а не как обязательная серверная часть продукта. Для этой задачи PHP-обработчик не требуется: браузер не принимает секреты и не сохраняет пользовательские данные на сервере.

{
  "dependencies": {
    "bootstrap": "5.3.8",
    "swiper": "14.4.0"
  }
}

Базовая разметка: контейнер, обёртка и слайды

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

CSS библиотеки обязателен. Без него JavaScript может создаться без явной ошибки, но карточки будут выглядеть как обычный столбец или получат неверную геометрию. Также контейнер должен иметь измеримую ширину. Если слайдер находится внутри CSS Grid или Flexbox, полезно задать родителю min-width: 0, чтобы длинное содержимое не растягивало страницу за пределы экрана.

<link rel="stylesheet" href="./vendor/swiper-bundle.min.css">
<div class="swiper catalog">
  <div class="swiper-wrapper">
    <div class="swiper-slide">Первая карточка</div>
    <div class="swiper-slide">Вторая карточка</div>
    <div class="swiper-slide">Третья карточка</div>
  </div>
  <div class="swiper-pagination"></div>
</div>
<script src="./vendor/swiper-bundle.min.js"></script>

Сначала создавайте DOM, затем экземпляр Swiper. Если данные приходят позже, обновляйте уже существующую структуру предусмотренным API или пересоздавайте блок контролируемо. Несколько экземпляров на одной странице должны получать собственные элементы навигации: общий селектор одной кнопки может случайно связать чужие карусели.

Первый запуск и кнопки, которые дополняют свайп

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

const slider = new Swiper(document.querySelector('.catalog'), {
  slidesPerView: 1,
  spaceBetween: 18,
  speed: 360,
  pagination: {
    el: document.querySelector('.catalog .swiper-pagination'),
    clickable: true
  },
  a11y: { enabled: true }
});
document.querySelector('#next').addEventListener('click', () => {
  slider.slideNext();
});

Свайп удобен на телефоне, но сам по себе не объясняет, что блок можно листать. Край следующей карточки, понятная подпись и кнопка «Далее» помогают обнаружить действие. Кнопки нужны и людям, которым неудобны точные жесты. Выбор номера особенно полезен в большом наборе: переход к карточке 150 не должен требовать ста сорока девяти нажатий.

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

Сценарий 1: адаптивный каталог и локальная подборка

В первом примере восемь учебных товаров. На узком экране помещается одна карточка и небольшой край следующей. На более широком — две или три. Количество определяется шириной самого контейнера, поэтому тот же блок можно вставить и в широкую страницу, и в боковую колонку кабинета. Для этого используется breakpointsBase: container, а не только ширина окна браузера.

const options = {
  slidesPerView: 1.08,
  breakpointsBase: 'container',
  breakpoints: {
    540: { slidesPerView: 2 },
    820: { slidesPerView: 3 }
  },
  spaceBetween: 18
};

Кнопка «В подборку» переключает состояние товара и обновляет список выбранного. Это демонстрация полезного действия внутри карусели, а не только перелистывания красивых прямоугольников. Состояние хранится в Set и исчезает при сбросе или смене сценария. В реальном магазине вместо него будет корзина с серверной проверкой цены, доступности и количества.

Не делайте всю карточку ссылкой, если внутри уже есть отдельная кнопка. Разделите переход к подробностям и добавление в подборку, задайте понятные названия и видимый результат. Если одновременно видны несколько карточек, номер позиции обозначает ведущий слайд области; соседние элементы продолжают оставаться доступными для чтения и выбора.

Сценарий 2: галерея товара, миниатюры и увеличение

Галерея состоит из двух экземпляров Swiper: основного изображения и ряда миниатюр. Модуль Thumbs связывает их, поэтому активная миниатюра меняется при перемещении большого изображения. Дополнительно миниатюры сделаны настоящими кнопками с русскими подписями: их можно выбрать клавиатурой, не полагаясь только на перетаскивание ленты.

const thumbs = new Swiper('.thumbs', {
  slidesPerView: 3,
  spaceBetween: 8,
  watchSlidesProgress: true
});
const gallery = new Swiper('.gallery', {
  thumbs: { swiper: thumbs },
  zoom: { minRatio: 1, maxRatio: 3 }
});
// У изображения должна быть обёртка .swiper-zoom-container.
gallery.zoom.in(2);
gallery.zoom.out();

В мастерской показаны шесть цветовых вариантов учебного светильника. Изображения — собственные SVG-иллюстрации, поэтому они сохраняют чёткость при увеличении и не требуют загрузки чужих фотографий. Кнопка увеличения показывает реальный Zoom, а возврат к масштабу один к одному убирает трансформацию. На телефоне изображение можно рассматривать внутри его рамки.

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

Сценарий 3: знакомство с сервисом и управляемое завершение

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

Такой блок полезен после регистрации или при появлении новой функции. Он должен объяснять действие, которое человек сможет выполнить дальше. Не растягивайте обязательную экскурсию на десятки экранов и не прячьте пропуск. Если сведения нужны повторно, оставьте доступ к ним в справке: пользователь мог закрыть знакомство, чтобы сначала решить срочную задачу.

slider.on('slideChange', () => {
  const last = slider.realIndex === steps.length - 1;
  finishButton.disabled = !last;
});
finishButton.addEventListener('click', () => {
  status.textContent = 'Знакомство завершено';
  // В приложении: сохранить прохождение через собственный API.
});

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

Сценарий 4: отзывы с автопоказом по желанию читателя

Автоматическая смена отзывов часто мешает: человек ещё читает, а текст уже исчезает. Поэтому в мастерской движение выключено до нажатия отдельной кнопки. После включения реальные слайды меняются каждые три с половиной секунды. Кнопка превращается в «Пауза», ручной переход останавливает показ, а Escape даёт быстрый способ прекратить движение.

const slider = new Swiper('.reviews', {
  effect: 'fade',
  fadeEffect: { crossFade: true },
  rewind: true,
  autoplay: {
    enabled: false,
    delay: 3500,
    disableOnInteraction: true,
    pauseOnMouseEnter: true
  }
});
// Только после явного действия пользователя:
slider.params.autoplay.enabled = true;
slider.autoplay.start();
// Постоянная остановка до следующей команды:
slider.autoplay.stop();

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

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

Сценарий 5: свободная лента карточек разной ширины

Не все наборы удобно нарезать на одинаковые экраны. Для тем, разделов и небольших подборок полезна свободная лента: пользователь перемещает её на произвольное расстояние. В примере карточки имеют разную ширину, slidesPerView установлен в auto, а модуль FreeMode сохраняет естественное продолжение движения. В режиме уменьшения движения инерция отключается.

new Swiper('.topics', {
  slidesPerView: 'auto',
  spaceBetween: 18,
  freeMode: { enabled: true, momentum: true },
  scrollbar: { el: '.topics-scrollbar', draggable: true }
});

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

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

Сценарий 6: стопка карточек с советами

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

new Swiper('.tips', {
  effect: 'cards',
  cardsEffect: { rotate: true, slideShadows: false },
  grabCursor: true,
  speed: 360
});

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

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

Сценарий 7: виртуальные карточки и переход к большому номеру

В седьмом сценарии находится двести учебных карточек. Модуль Virtual хранит набор данных, но создаёт в DOM только небольшое окно элементов вокруг текущей позиции. Под примером показаны оба числа, поэтому разницу можно увидеть непосредственно. Перейдите к карточке 150 и убедитесь, что не требуется последовательно пролистывать весь предыдущий материал.

new Swiper('.lessons', {
  slidesPerView: 1.08,
  virtual: {
    enabled: true,
    slides: lessons,
    cache: false,
    addSlidesBefore: 1,
    addSlidesAfter: 1,
    renderSlide(item, index) {
      return `<div class="swiper-slide">${escapeHTML(item.title)}</div>`;
    }
  }
});

Это оптимизация DOM, а не серверная пагинация. Все двести записей уже загружены в браузер и доступны JavaScript. Если набор содержит десятки тысяч тяжёлых объектов или персональные сведения, его надо получать частями через API и контролировать доступ на сервере. Нельзя считать скрытую или ещё не нарисованную карточку защищённой.

Пользовательские строки при генерации HTML необходимо экранировать. В исходниках для этого используется небольшая функция escape, а данные примера контролируются автором. Для произвольной разметки из внешней системы лучше создавать DOM через textContent или применять проверенную очистку HTML. Виртуализация не должна превращаться в канал выполнения чужого JavaScript.

Сценарий 8: вертикальная история обновлений

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

new Swiper('.updates', {
  direction: 'vertical',
  spaceBetween: 14,
  pagination: { el: '.updates-position', type: 'fraction' }
});

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

Колесо мыши остаётся у страницы. На сенсорном экране вертикальный жест внутри виджета может конкурировать с прокруткой документа, поэтому кнопочная альтернатива особенно важна. Если тестирование показывает, что посетители застревают в блоке, уберите перетаскивание или выберите горизонтальное расположение. Направление движения должно помогать задаче, а не демонстрировать количество доступных параметров.

Breakpoints, loop и параметры, которые требуют пересоздания

Breakpoints удобно использовать для количества видимых карточек, промежутков и группировки. Но не всякую настройку можно безопасно менять таким способом. В частности, изменение эффекта или режима loop затрагивает внутреннюю структуру. В нашей панели такие изменения приводят к удалению экземпляра и созданию нового с согласованными параметрами.

У loop есть требования к количеству элементов и сочетанию с размером видимой группы. Поэтому мы не включаем его автоматически во всех сценариях. Для учебного каталога восьми карточек достаточно при показе до трёх одновременно. Для последовательного знакомства или истории обновлений бесконечное движение только запутало бы смысл начала и конца.

// Когда изменилась структура или эффект:
current.destroy(true, true);
current = new Swiper(container, nextOptions);

// Когда изменился размер уже существующей области:
current.update();

Если карусель открывается в скрытой вкладке, модальном окне или сворачиваемой панели, проверяйте размеры после показа. Автоматическое наблюдение помогает, но не заменяет понимание жизненного цикла вашего компонента. Для всплывающих элементов и привязки к кнопкам пригодится отдельный материал о Floating UI; не смешивайте позиционирование панели с прокруткой её содержимого.

Доступность: клавиатура, подписи и текстовая альтернатива

Модуль A11y добавляет объявления и служебные подписи, но он не знает смысл ваших кнопок и изображений. В мастерской сообщения переведены на русский, миниатюры имеют названия, кнопки достаточно крупные, а изменение текущего слайда отражается в текстовом статусе. Декоративные символы скрыты от вспомогательных технологий, чтобы они не перебивали полезное содержание.

a11y: {
  enabled: true,
  prevSlideMessage: 'Предыдущий слайд',
  nextSlideMessage: 'Следующий слайд',
  paginationBulletMessage: 'Перейти к слайду {{index}}',
  slideLabelMessage: '{{index}} из {{slidesLength}}'
}

Клавиатурное управление активируется, когда фокус находится внутри основного слайдера, и выключается после выхода. Это важно на длинной странице: стрелки не должны внезапно менять карусель, пока человек работает с другим полем. Элементы управления невидимых карточек исключаются из обычного Tab-порядка; видимые действия остаются доступны.

Под блоком можно раскрыть текст текущей карточки. Это полезная альтернатива для содержания, но не полноценная сертификация доступности всего сайта. Проверяйте реальный Tab-порядок, увеличение текста, чтение вашим скринридером и контраст после замены цветов. Сам факт подключения A11y не означает, что любой сложный HTML внутри слайда автоматически стал удобным.

Уменьшение движения и уважение к настройкам устройства

Некоторым людям постоянные перемещения мешают читать или вызывают физический дискомфорт. Браузер передаёт системное предпочтение через prefers-reduced-motion. В мастерской оно имеет приоритет: нулевая скорость перехода, отключённый автопоказ, отсутствие инерции свободной ленты, обычные слайды вместо стопки и Fade. Дополнительный переключатель позволяет попробовать этот вариант прямо на странице.

const motion = matchMedia('(prefers-reduced-motion: reduce)');
const reduced = motion.matches || settings.reduce;
const speed = reduced ? 0 : settings.speed;

motion.addEventListener('change', () => {
  // Пересоздать пример с новыми настройками и очистить старый.
  remount();
});

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

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

Мобильная версия: ширина, касания и длинные подписи

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

Минимальная полезная проверка — ширины около 390 и 296 CSS-пикселей, а также увеличение текста. При этом виртуальный viewport браузера не равен испытанию на настоящем телефоне: физический свайп, экранная клавиатура и конкретный мобильный браузер требуют отдельного просмотра. Не делайте вывод о поддержке всех устройств только по отсутствию горизонтальной прокрутки в одном размере.

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

События и подключение к данным вашего приложения

Событие slideChange позволяет синхронизировать заголовок, выбранную миниатюру, счётчик или внешнюю панель. Для циклического режима обычно нужен realIndex: он отражает индекс исходных данных. Не отправляйте серверный запрос на каждое случайное перемещение, если результат никому не нужен. Аналитика, подгрузка и сохранение пользовательского выбора имеют разные требования и должны подключаться осознанно.

slider.on('slideChange', () => {
  const item = products[slider.realIndex];
  title.textContent = item.title;
});

const response = await fetch('/api/products?collection=desk');
if (!response.ok) throw new Error('Не удалось получить подборку');
const items = await response.json();
// Проверить структуру данных, затем создать карточки через textContent.
// После изменения размеров и набора вызвать update или пересоздать блок.

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

На PHP-сайте сервер может сразу отдать карточки в HTML, а JavaScript только улучшит их поведение. Это часто проще, чем создавать отдельный API для небольшого блока. Для интерактивных состояний без большого фреймворка полезна также статья об Alpine.js. Выбирайте количество инструментов по реальной сложности страницы.

Изображения, виртуализация и производительность

Главный вес карусели нередко находится в изображениях, а не в библиотеке. Подготовьте подходящие размеры, используйте современные форматы и не загружайте огромную фотографию для маленькой миниатюры. Для изображений вне первого экрана может помочь loading=”lazy”, но главное изображение страницы иногда нужно загружать сразу. Ширина и высота в разметке помогают резервировать место и уменьшать скачки.

<img src="lamp-900.webp"
     srcset="lamp-450.webp 450w, lamp-900.webp 900w"
     sizes="(max-width: 600px) 100vw, 700px"
     width="900" height="600"
     loading="lazy"
     alt="Настольный светильник с мятным корпусом">

Virtual уменьшает число DOM-узлов, но не делает бесконечный набор бесплатным. Данные, обработчики и изображения всё равно занимают память. Счётчик в нашем примере помогает увидеть именно выигрыш по смонтированным слайдам. Для большого рабочего каталога измеряйте загрузку, память и время реакции на реальном устройстве, а не только количество элементов.

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

Очистка экземпляров и возврат на страницу

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

function cleanup() {
  slider.destroy(true, true);
  thumbnails?.destroy(true, true);
  removeApplicationListeners();
}
addEventListener('pagehide', event => {
  if (event.persisted) slider.autoplay?.stop();
  else cleanup();
});

У события pagehide есть особенность: браузер может сохранить страницу в кэше возврата назад. Если безусловно удалить интерфейс в этот момент, после кнопки «Назад» пользователь иногда увидит пустую область. Поэтому при persisted мы сохраняем экземпляр, но останавливаем движение. При обычном уходе выполняется полная очистка.

Такие детали особенно важны в кабинетах, где компоненты появляются и исчезают без полной перезагрузки. В React, Vue или другом фреймворке очистку связывают с жизненным циклом компонента. В обычном JavaScript эту дисциплину надо организовать самостоятельно, как сделано в исходниках мастерской.

Копирование и скачивание точного примера

Генератор использует ту же функцию mountExperience, которая создаёт текущий интерфейс. В HTML включаются выбранный сценарий, его данные, параметры и авторские стили. Поэтому пример с виртуальными карточками действительно содержит Virtual, а галерея действительно создаёт Thumbs и Zoom. Это не универсальный короткий фрагмент, который лишь приблизительно напоминает увиденное.

Скачанный HTML положите в public полного проекта. Рядом должна находиться папка vendor с тремя локальными файлами. После запуска сервера откройте адрес файла, например /swiper-gallery.html. Отдельный HTML не включает саму библиотеку внутрь: это уменьшает дублирование и сохраняет понятную структуру. Если перенести только его на другой сервер, пути к ресурсам тоже нужно перенести или исправить.

public/
  swiper-gallery.html
  vendor/
    bootstrap.min.css
    swiper-bundle.min.css
    swiper-bundle.min.js

Текущая позиция, подборка товаров и включённый автопоказ не сохраняются: новый пример стартует с начала. Системная настройка уменьшения движения проверяется на устройстве, где его открыли. Копирование использует Clipboard API; если браузер запрещает доступ, код выделяется для ручного копирования и остаётся кнопка скачивания. На публичном сайте штатный доступ к буферу требует HTTPS и разрешения браузера.

Запуск на Windows: готовая статика и изменение исходников

Распакуйте архив и откройте PowerShell внутри swiper-project. Для готовой страницы достаточно Node.js 24 и команды локального сервера: public уже собран. Сервер слушает только 127.0.0.1, поэтому учебный просмотр не открывает компьютер для внешних подключений. Перейдите по адресу в браузере и остановите процесс сочетанием Ctrl+C, когда закончите.

node --version
node scripts/server.mjs
# В браузере: http://127.0.0.1:8141/

Если нужно изменить данные, стили или поведение, установите зависимости из lock-файла, отредактируйте src и повторите сборку. Команда npm ci использует зафиксированные версии. Сборка переносит авторские файлы и vendor в public; тесты проверяют реальные экземпляры библиотеки в DOM-среде. Не редактируйте сгенерированный public, если потом собираетесь запускать build: ваши изменения могут быть заменены исходниками.

npm ci
npm run build
npm test
# Если основной порт занят:
$env:PORT = '8148'
node scripts/server.mjs

Открытие index.html двойным щелчком через file:// не эквивалентно серверу. Модульные импорты и чтение CSS для генератора должны работать через HTTP. Готовые файлы можно также разместить в локальном PHP-окружении: исполнять PHP для самого слайдера при этом не требуется.

Запуск на Linux и размещение готового public

На Linux используются те же исходники и тот же lock-файл. Установите поддерживаемый Node.js 24 способом, принятым в вашей среде, распакуйте проект и запустите локальный сервер. Команды npm не требуют sudo внутри каталога пользователя. Если права на node_modules пришлось постоянно исправлять от root, лучше проверить способ установки Node и владельца рабочей папки.

unzip swiper-project.zip
cd swiper-project
node --version
node scripts/server.mjs
# Для разработки:
npm ci
npm run build
npm test
# Другой порт:
PORT=8148 node scripts/server.mjs

Для публичного сервера не обязательно держать этот Node-процесс работающим. Проект статический: Nginx, Caddy или обычный хостинг могут отдавать public напрямую. При таком размещении Node нужен только там, где вы собираете новую версию. Это уменьшает количество постоянно работающих служб и упрощает обслуживание небольшого сайта.

Document root должен указывать именно на public, а не на корень всего скачанного проекта. Исходники, тесты, npm-метаданные и локальный сервер не нужны посетителю для работы мастерской. Проверьте MIME для .js, отсутствие ошибок загрузки и относительные пути, особенно если размещаете интерфейс не в корне домена, а в подпапке существующего сайта.

Linux VPS: домен, HTTPS, доступ и журнал запросов

В архиве есть пример Caddyfile для отдельного домена. Предполагается VPS с установленным Caddy, настроенной DNS-записью и доступными портами 80 и 443. HTTPS оформляется средствами Caddy. Добавьте отдельный блок к текущей конфигурации, сохранив остальные сайты; затем проверьте конфигурацию и только после успешной проверки перезагрузите сервис.

slider.example.com {
    root * /srv/swiper/current/public
    encode zstd gzip
    file_server
    header X-Content-Type-Options nosniff
    log
}
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://slider.example.com/
curl -I https://slider.example.com/app.js
sudo journalctl -u caddy --since '10 minutes ago' --no-pager

Команды с sudo меняют системную конфигурацию и предполагают соответствующие права. Сам public должен быть доступен сервисному пользователю для чтения. Подробная схема размещения каталогов приведена в README, а объяснение HTTPS и конфигурации сервера — в материале о Caddy. Журнал запросов помогает обнаружить отсутствующий vendor-файл или ошибочный путь после публикации.

Публичной учебной мастерской вход не нужен. Закрытую корпоративную подборку защищайте на уровне всего сайта или приложения, включая ресурсы. Для небольшого стенда допустим basic_auth Caddy с хешем пароля; для личного кабинета используйте общую авторизацию. Секреты нельзя помещать в JavaScript: скачав страницу, посетитель получает её клиентские данные независимо от того, какой слайд сейчас виден.

Обновление библиотеки, новая версия сайта и быстрый откат

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

На сервере храните отдельные каталоги релизов. Новый архив распаковывается в новый каталог, а ссылка current переключается после проверки файлов. Так откат возвращает весь согласованный набор HTML, CSS и JavaScript. Не заменяйте файлы по одному на живой странице: посетитель может получить смесь старых и новых ресурсов.

# После распаковки нового релиза и проверки public/index.html:
sudo ln -s /srv/swiper/releases/r2/swiper-project /srv/swiper/current.next
sudo mv -Tf /srv/swiper/current.next /srv/swiper/current

# Откат к сохранённому r1:
sudo ln -s /srv/swiper/releases/r1/swiper-project /srv/swiper/current.rollback
sudo mv -Tf /srv/swiper/current.rollback /srv/swiper/current

Эти команды рассчитаны на Linux и существующую структуру из README; временные ссылки должны отсутствовать до выполнения. Долгий immutable-кэш подходит хешированным именам ресурсов. Для постоянного app.js такая политика может удержать старый интерфейс после обновления. После переключения проверяйте не только HTTP 200, но и реальное открытие страницы, навигацию, экспорт и журнал ошибок.

Что проверяют тесты и как развивать мастерскую дальше

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

Для DOM-тестов используется JSDOM с заданной геометрией. Он не рисует экран, поэтому эти проверки не доказывают качество визуальной композиции, физический свайп или совместимость со всеми скринридерами. Мобильную вёрстку и настоящие браузерные действия проверяют отдельно. После замены содержимого своими текстами повторите такой просмотр: длинная подпись может выявить проблему, которой не было в учебных данных.

Дальше можно подключить свою коллекцию через API, добавить сохранение подборки в профиль, связать галерею с выбором цвета или заменить советы рабочими инструкциями. Для перестановки элементов пользователем пригодится SortableJS, а для аналитики по данным — Apache ECharts. Начинайте с понятной задачи и оставляйте пользователю видимый результат каждого действия.

Официальные материалы: API и параметры Swiper, демонстрации возможностей, история изменений, исходники и лицензия, статическая выдача Caddy. Полный архив мастерской содержит готовую страницу, авторский код, локальные зависимости, тесты и инструкции для Windows и Linux.