PhotoSwipe: галерея изображений — 8 сценариев и мастерская
Создаём удобную галерею для портфолио, статей и вложений. Восемь живых сценариев PhotoSwipe, настройки, генератор кода и готовый проект с размещением на Linux VPS.

PhotoSwipe превращает набор небольших изображений в удобный просмотрщик: картинка открывается поверх страницы, её можно увеличить, сдвинуть, переключить стрелками или закрыть клавишей Escape. Это полезно в портфолио, каталоге товаров, базе знаний, отчёте о выполненной работе и карточке заказа с вложениями. Человеку не приходится открывать каждое изображение в новой вкладке и искать дорогу обратно.
Здесь работает настоящая PhotoSwipe 5.4.4. В мини-мастерской восемь сценариев, шесть собственных иллюстраций блога, фильтрация, подписи, загрузка текущего изображения и генератор JavaScript. Можно попробовать настройки, скачать код и весь проект. Дальше разберём устройство галереи, подготовку картинок, интеграцию с PHP и размещение на Linux VPS. Для запуска примера есть отдельные команды Windows и Linux.
Что получает пользователь и где пригодится PhotoSwipe
Представьте карточку выполненного проекта: шесть иллюстраций показывают интерфейс, структуру данных и результат работы. В сетке они занимают мало места, но текст на схеме не читается. Нажатие открывает крупную версию, увеличение позволяет рассмотреть деталь, а стрелка переводит к следующему шагу. При закрытии человек остаётся в том же контексте страницы. Именно этот путь и стоит проектировать, а не просто эффект появления большой картинки.
В интернет-магазине галерея помогает рассмотреть фактуру и комплектацию. В сервисном кабинете — приложенный скриншот ошибки. В инструкции — последовательность настройки. В отчёте — состояние объекта до и после работ. Содержание может быть разным, но требования похожи: понятный порядок, подпись, доступное управление и разумное время загрузки. Для каждого такого сценария PhotoSwipe отвечает за окно просмотра, а ваше приложение определяет, какие файлы в нём доступны.
Чем галерея отличается от слайдера и файлового хранилища
Слайдер обычно занимает место внутри страницы и постоянно показывает один из слайдов. PhotoSwipe открывает отдельный диалог поверх материала. Это хороший выбор, когда основное содержание — текст или карточки, а крупное изображение нужно по запросу. Для автоматической карусели баннеров лучше выбрать другой компонент: бесконечная смена рекламных экранов не является задачей нашего просмотрщика.
Библиотека также не загружает пользовательские файлы на сервер, не проверяет права доступа, не создаёт миниатюры и не сжимает исходники. Эти операции принадлежат приложению. В наших примерах картинки уже подготовлены и лежат рядом со страницей. Для формы загрузки пригодится материал о FilePond, а для подготовки нескольких размеров — серверная обработка изображений. Связать эти этапы можно одним каталогом метаданных: адрес, ширина, высота, описание и порядок.
Мини-мастерская: восемь способов использовать галерею
Начните со сценария «Портфолио»: откройте обложку, перейдите к соседней и увеличьте изображение. Затем попробуйте каталог с фильтром: в просмотрщике останутся только карточки выбранной темы. В сценарии вложений появится скачивание текущего файла, а в сценарии спокойного интерфейса можно убрать анимацию. Под галереей выводятся реальные события PhotoSwipe, поэтому видно, что произошло после действия.
Состояние мастерской хранится в открытой вкладке. Она не отправляет ваши настройки на сервер и не создаёт пользовательский аккаунт. Генератор показывает минимальный JavaScript для выбранной подборки и параметров; полный код подписей, кнопок и интерфейса находится в архиве. Демонстрационные изображения — обложки этого сайта, созданные с помощью генерации изображений. Здесь нет фотографий людей, документов клиентов или скрытых внешних запросов к фотобанку.
Просмотрщик внутри статьи ограничен рамкой мастерской. Для комфортного увеличения на телефоне откройте мастерскую отдельно.
Версия, бесплатные возможности и структура проекта
В проекте зафиксирована PhotoSwipe 5.4.4 под лицензией MIT. Это проверенная стабильная версия серии 5; сведения о разрабатываемой следующей версии не означают, что нужно устанавливать предварительный релиз. Bootstrap 5.3.8 используется только для базовых элементов страницы. React, Vue и Angular здесь не требуются: вся логика написана на обычном JavaScript с ES-модулями.
Папка public содержит готовую страницу, стили, каталог изображений и локальные зависимости. Исходник app.js связывает интерфейс с библиотекой, model.js отвечает за выборку и генерацию примера. В scripts лежат сборка и локальный HTTP-сервер. Каталог tests содержит проверки данных и рецептов. В deploy находится Caddyfile, а в examples/php — небольшой настоящий PHP-эндпоинт для выдачи каталога. Это позволяет сначала попробовать готовое, а затем заменить только нужный слой.
npm ci
npm run build
npm test
npm start
Как устроены Lightbox, Core и CSS
Lightbox следит за нажатием на элементы галереи и подготавливает открытие. Core создаёт сам диалог, переключает слайды и управляет масштабом. CSS оформляет просмотрщик. Такое разделение удобно на статье с большим количеством текста: основной модуль можно загружать только тогда, когда человек решил открыть картинку. В нашем проекте все файлы доступны локально, поэтому работа не зависит от внешнего CDN.
Инициализация привязывает экземпляр к конкретной галерее. Селектор children должен находить именно ссылки на изображения, а не любые вложенные элементы. Если на странице есть другие кнопки или ссылки на описание проекта, они не должны случайно становиться слайдами. Для нескольких независимых подборок создают отдельные контейнеры либо используют подходящий общий селектор, сохраняя понятные границы навигации.
import PhotoSwipeLightbox from './vendor/photoswipe-lightbox.esm.js';
const lightbox = new PhotoSwipeLightbox({
gallery: '#gallery',
children: 'a',
pswpModule: () => import('./vendor/photoswipe.esm.js')
});
lightbox.init();
Разметка: ссылка, размеры и описание изображения
Основой служит обычная ссылка на крупное изображение, внутри которой находится миниатюра. Атрибуты data-pswp-width и data-pswp-height задают реальные размеры большого файла. PhotoSwipe использует их для расчёта масштаба до загрузки изображения. Если перепутать ширину и высоту или указать размеры миниатюры, появятся неправильные пропорции и скачки при открытии.
У ссылки есть самостоятельная польза: браузер может открыть изображение даже без просмотрщика. В серверной странице такую разметку лучше выдавать сразу вместе с HTML. Наша мастерская загружает каталог через fetch, поэтому при отключённом JavaScript сама сетка не строится; для обычного публичного портфолио предпочтителен серверный вывод ссылок. Подпись оформляем через figure и figcaption, а alt кратко объясняет содержание изображения.
<figure>
<a href="images/project.webp"
data-pswp-width="1672" data-pswp-height="941">
<img src="images/project-480.webp" width="480" height="270"
alt="Схема обработки заявки" loading="lazy">
</a>
<figcaption>Заявка проходит проверку и попадает в очередь.</figcaption>
</figure>
1. Портфолио: показать работу и сохранить контекст
В портфолио важна связь изображения с задачей. Под карточкой можно написать, что именно сделано: редактор обращения, схема интеграции, календарь записи. Пользователь сначала выбирает интересный проект, затем рассматривает детали. Не стоит превращать подпись в длинное резюме: основное описание остаётся на странице, а просмотрщик помогает изучить визуальную часть.
В мастерской этот сценарий показывает шесть работ в сетке. На узком экране число колонок уменьшается. Высота карточки зависит от подписи, но размеры изображения известны заранее и не вызывают сдвигов при загрузке. После закрытия диалога нужно убедиться, что клавиатурный фокус вернулся к исходной ссылке: иначе посетитель с клавиатурой потеряет место и будет вынужден заново проходить всю страницу.
2. Иллюстрации статьи: подпись должна оставаться доступной
Для инструкции картинка без объяснения часто бесполезна. Подпись должна назвать действие, условие или результат: например, какой параметр изменить и что появится после сохранения. В сценарии статьи используются три более крупные карточки с текстом рядом. На телефоне подпись располагается под изображением, поэтому её можно прочитать без открытия диалога.
В PhotoSwipe 5 подписи добавляются через API. В нашей реализации отдельный элемент обновляется при смене слайда. Текст присваивается через textContent, поэтому строка из каталога не превращается в исполняемую HTML-разметку. Это особенно существенно, когда описание приходит из CMS. Если продукту действительно требуется форматированный текст, понадобится отдельная политика разрешённых тегов и очистка HTML.
lightbox.on('uiRegister', () => {
lightbox.pswp.ui.registerElement({
name: 'custom-caption', appendTo: 'root', isButton: false,
onInit: (el, pswp) => {
pswp.on('change', () => {
el.textContent = items[pswp.currIndex].caption;
});
}
});
});
3. Масштаб: рассмотреть схему, а не растянуть миниатюру
Увеличение полезно для интерфейсных скриншотов, диаграмм, чертежей и деталей товара. Но кнопка масштаба не создаёт дополнительной информации. Если исходник имеет ширину 800 пикселей, растягивание на большой экран только покажет пиксели крупнее. Подготавливайте изображение под задачу и проверяйте читаемость важного фрагмента на реальном размере, а не только красивый вид миниатюры.
В нашей мастерской вторичный масштаб равен двум, максимальный — трём. Это демонстрационные параметры; для фотографий и схем они могут различаться. В просмотрщике работают кнопка увеличения и перемещение увеличенной картинки. На сенсорном устройстве библиотека поддерживает жесты, однако проверка узкого viewport не заменяет проверку пальцами на физическом телефоне. Не убирайте видимые кнопки, полагаясь исключительно на жесты.
const options = {
secondaryZoomLevel: 2,
maxZoomLevel: 3,
zoomTitle: 'Масштаб'
};
4. Фильтры: слайды должны соответствовать видимой выборке
Допустим, посетитель выбрал только серверные проекты. Если после открытия первой карточки стрелка неожиданно покажет скрытый интерфейсный проект, фильтр будет восприниматься как сломанный. Поэтому источник слайдов нужно строить из той же выборки, которая отображается в сетке. Индекс текущего изображения относится к этой выборке, а не к исходному каталогу всех файлов.
Для небольшого каталога проще пересобрать сетку и создать новый Lightbox. Сначала вызываем destroy у прежнего экземпляра, затем обновляем разметку и выполняем init у нового. Это не самый экономный способ для тысяч изображений, зато понятный и надёжный для десятков карточек. Для большого каталога нужны серверная пагинация, стабильные идентификаторы и заранее определённые правила навигации между страницами.
const visible = category === 'all'
? items
: items.filter(item => item.category === category);
lightbox?.destroy();
renderGallery(visible);
lightbox = createLightbox();
lightbox.init();
5. Миниатюры и srcset: загрузить столько, сколько нужно
В архиве для каждой иллюстрации подготовлены три размера: миниатюра 480 пикселей, средний вариант 960 и оригинал 1672. Сетка использует миниатюры; просмотрщик получает варианты через data-pswp-srcset. При открытии и увеличении браузер выбирает подходящий ресурс. В журнале мастерской можно увидеть имя реально выбранного файла. Повторное открытие может использовать кеш браузера, поэтому сетевой запрос не обязан повторяться.
Ширина и высота в метаданных должны описывать самый большой вариант. Все размеры одного изображения сохраняют одинаковое соотношение сторон. Если миниатюра специально обрезана, библиотеке нужно сообщить об этом отдельно; иначе анимация открытия будет выглядеть неправильно. Не делайте один srcset из разных кадров: это набор разрешений одного изображения, а не способ переключать содержание.
<a href="images/project.webp"
data-pswp-width="1672" data-pswp-height="941"
data-pswp-srcset="images/project-960.webp 960w, images/project.webp 1672w">
<img src="images/project-480.webp" alt="Проект" width="480" height="270">
</a>
6. Программное открытие: изображения в строке заказа
Не всегда нужна большая сетка. В таблице заказов может быть действие «Посмотреть вложения», а в сообщении поддержки — несколько маленьких значков. Тогда приложение передаёт данные и вызывает открытие из обработчика кнопки. Важно сохранить связь с выбранной записью: пользователь должен увидеть вложения текущего заказа, а не общий список файлов всей системы.
В сценарии «Открыть из списка» выбирается конкретная работа и нажимается отдельная кнопка. Метод loadAndOpen получает индекс в текущей галерее. Для настоящего кабинета список файлов следует получать с сервера после проверки прав; скрыть чужую ссылку в интерфейсе недостаточно. Сам PhotoSwipe не знает, кто вошёл в систему и какие документы ему разрешено смотреть.
document.querySelector('#open-selected').addEventListener('click', () => {
const index = Number(document.querySelector('#start-image').value);
lightbox.loadAndOpen(index);
});
7. Скачивание: действие относится к текущему файлу
В галерее вложений полезно дать человеку возможность сохранить изображение. Кнопка должна менять адрес вместе со слайдом. Частая ошибка — присвоить ссылку один раз при открытии, после чего она продолжает скачивать первую картинку даже на третьем слайде. В нашей мастерской адрес обновляется на событии change и берётся только из проверенного локального каталога.
Атрибут download удобен для файлов того же сайта. Для другого домена поведение может отличаться, а для приватных вложений лучше использовать серверный маршрут скачивания с проверкой доступа и правильным Content-Disposition. Не передавайте в такой маршрут произвольный путь к файлу. Идентификатор вложения должен разрешаться сервером в заранее известный объект хранилища.
lightbox.on('change', () => {
const item = visible[lightbox.pswp.currIndex];
downloadLink.href = item.src;
downloadLink.setAttribute('download', '');
});
8. Анимации и фон: комфорт важнее эффектности
Плавное открытие из миниатюры помогает понять, откуда появилась большая картинка. Но длинная анимация при каждом просмотре раздражает, особенно когда человек последовательно проверяет десятки вложений. В рабочем интерфейсе лучше короткий переход и предсказуемые кнопки. Для пользователей, которым движение доставляет дискомфорт, учитывается системная настройка prefers-reduced-motion.
В мастерской можно отключить анимацию и изменить плотность фона. Эти настройки применяются при следующем открытии, что прямо указано в интерфейсе. Полностью тёмный фон удобно использовать для схем и документов; полупрозрачный лучше сохраняет ощущение страницы под диалогом. Следите, чтобы подписи и элементы управления оставались контрастными при любом выбранном фоне.
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
const options = {
bgOpacity: 0.94,
showHideAnimationType: reduceMotion ? 'none' : 'zoom',
showAnimationDuration: reduceMotion ? 0 : 250,
hideAnimationDuration: reduceMotion ? 0 : 250,
zoomAnimationDuration: reduceMotion ? 0 : 250
};
События: что измерять и как не перегрузить журнал
События помогают связать просмотрщик с приложением: узнать об открытии, смене слайда, загрузке изображения и закрытии. В демонстрации журнал ограничен двенадцатью строками. Он показывает действие и текущий файл, но не сохраняется после перезагрузки. Это позволяет разобраться в последовательности без сотен технических сообщений и бесконечного роста DOM.
В рабочем продукте имеет смысл измерять ошибки загрузки и востребованность просмотра, если это отвечает вашей задаче и правилам обработки данных. Не отправляйте в аналитику приватные URL с токенами, названия клиентских документов и полный текст подписей. Обычно достаточно типа события, обезличенного идентификатора и технического результата. Для диагностики сначала воспроизведите проблему локально с тем же размером и форматом изображения.
lightbox.on('afterInit', () => log('Просмотр открыт'));
lightbox.on('change', () => log('Слайд ' + (lightbox.pswp.currIndex + 1)));
lightbox.on('close', () => log('Просмотр закрыт'));
Каталог из PHP: разделяем данные и отображение
Если изображения принадлежат товарам или проектам, их метаданные обычно хранятся на сервере. PHP выбирает разрешённые записи и возвращает JSON либо сразу формирует HTML. В архиве есть простой read-only эндпоинт examples/php/catalog.php: он читает наш учебный каталог, принимает только известные категории и выдаёт массив. Это выполняемый пример передачи данных, а не полноценная система управления медиафайлами.
При интеграции с базой данных адреса лучше формировать из доверенного идентификатора и известного каталога хранения. Пользовательский параметр не должен становиться путём файловой системы. Если галерея публичная, JSON можно кешировать по версии каталога. Если приватная — сначала проверяются пользователь и права на объект, затем формируется ограниченный список доступных вложений и, при необходимости, краткоживущие ссылки.
const response = await fetch('/api/gallery?project=42');
if (!response.ok) throw new Error('Каталог недоступен');
const items = await response.json();
// Проверяем размер массива, поля и допустимые адреса.
// Только после этого строим DOM или dataSource.
Ошибки, пустые подборки и небезопасные данные
Изображение может быть удалено, сеть — недоступна, а пользователь — лишиться права просмотра. Покажите понятную ошибку, оставьте возможность закрыть диалог и вернуться к карточке. Пустая выборка должна объяснять причину и предлагать сбросить фильтр. Бесконечный индикатор загрузки без действия не помогает ни посетителю, ни поддержке.
В мастерской каталог ограничен сорока элементами, размеры — тремя тысячами пикселей по стороне, а пути разрешены только внутри images. Это правила конкретного учебного набора. Они не заменяют серверную проверку загрузок: файл может иметь неверный MIME, неожиданные размеры или опасное содержимое. HTML-подписи не вставляются через innerHTML, а внешние пользовательские URL не используются как доверенные адреса скачивания.
Доступность: клавиатура, фокус и понятные названия
Просмотрщик должен открываться клавиатурой, закрываться Escape и давать возможность перейти к следующему изображению без мыши. Кнопки получают русские названия: «Закрыть», «Масштаб», «Предыдущее», «Следующее». Видимый фокус помогает понять, какое действие будет выполнено. Сами иллюстрации сопровождаются alt и подписью, доступной вне модального окна.
При проверке пройдите полный путь: Tab до карточки, Enter для открытия, стрелка для переключения, Escape для закрытия и следующий Tab. Затем повторите для кнопки программного открытия. У разных точек входа может отличаться возврат фокуса. Не отключайте встроенное управление фокусом без веской причины: на длинной статье потеря позиции особенно заметна.
Мобильная версия и ограничения встроенной мастерской
На телефоне галерея должна помещаться по ширине без прокрутки всей страницы вбок. Кнопки фильтра и выбора сценария переносятся на отдельные строки, а подписи не обрезаются до нескольких непонятных слов. Для редакционной подборки изображение и текст складываются вертикально. Большие фрагменты кода прокручиваются внутри своего блока.
Встроенная мастерская находится в iframe. Поэтому её модальное окно перекрывает только внутреннюю область, а не всю статью. Это нормальное поведение браузера, но для изучения деталей удобнее отдельная страница мастерской. В самостоятельном проекте просмотрщик занимает viewport этого проекта. Проверять нужно и узкий экран, и портретное/альбомное положение, и фактические жесты на устройстве, если галерея становится частью вашего продукта.
Windows: запустить готовый проект локально
Установите поддерживаемую Node.js 24, распакуйте архив и откройте PowerShell в папке проекта. Команда npm ci использует package-lock.json, поэтому зависимости совпадают с проверенной сборкой. Сборка копирует локальные файлы PhotoSwipe и Bootstrap. Локальный сервер нужен для ES-модулей и fetch: открытие index.html через file:// не является рабочим способом запуска этого проекта.
node --version
npm ci
npm run build
npm test
npm start
# Откройте http://127.0.0.1:8114/
Порт можно сменить только для текущего процесса через переменную окружения. Сервер слушает loopback и предназначен для разработки. Он не открывает папку проекта целиком: доступны файлы public. Для остановки используйте Ctrl+C в терминале, где выполняется npm start. Не нужно завершать все процессы Node.js на компьютере — среди них могут быть другие проекты.
$env:PORT = "8124"
npm start
# После остановки сервера:
Remove-Item Env:PORT
Linux: тот же проект и отдельная проверка PHP
На Linux порядок сборки такой же. Права на файлы должны позволять чтение пользователю, от которого работает сервер. Не запускайте npm install от root в домашнем каталоге другого пользователя: это часто оставляет файлы, которые затем нельзя обновить без sudo. Для чистой установки используйте npm ci, а не произвольное обновление зависимостей перед публикацией.
node --version
npm ci
npm run build
npm test
PORT=8114 npm start
Чтобы попробовать PHP-выдачу каталога, отдельно запустите встроенный сервер PHP 8.3 или новее из examples/php. Он также предназначен только для локальной проверки. Откройте адрес с категорией interface и сравните результат с исходным JSON: должны вернуться три записи. Неизвестная категория возвращает ошибку 400. Для обычной статической галереи этот сервер вообще не требуется.
php -S 127.0.0.1:8116 -t examples/php
# В другом терминале:
curl "http://127.0.0.1:8116/catalog.php?category=interface"
Linux VPS: публикация готовой статики и HTTPS
После локальной проверки галерею можно разместить на обычном статическом хостинге или VPS. На сервер отправляется public, а исходники и node_modules не должны становиться публичной корневой папкой. В примере Caddy выдаёт файлы из /srv/photoswipe/current/public. Домен заранее направляют на IP сервера, а входящие порты 80 и 443 открывают для HTTP/HTTPS. Установка Caddy подробно разобрана в отдельной статье сайта.
Для обновлений удобно хранить версии в releases и переключать символьную ссылку current. Каталог выпуска создаётся с новым именем, файлы копируются туда, затем проверяется index.html и только после этого меняется ссылка. Пользователь caddy должен иметь право прохода по родительским каталогам и чтения файлов. Не выдавайте веб-серверу право записи в опубликованные исходники без необходимости.
sudo install -d -m 755 /srv/photoswipe/releases/20261107/public
sudo cp -a public/. /srv/photoswipe/releases/20261107/public/
sudo chown -R root:caddy /srv/photoswipe/releases/20261107
sudo find /srv/photoswipe/releases/20261107 -type d -exec chmod 755 {} \;
sudo find /srv/photoswipe/releases/20261107 -type f -exec chmod 644 {} \;
sudo ln -s /srv/photoswipe/releases/20261107 /srv/photoswipe/current
В deploy/Caddyfile замените переменную SITE_ADDRESS своим доменом либо задайте её в окружении службы. Конфигурацию можно импортировать из основного Caddyfile, если на сервере уже размещены другие сайты. Не заменяйте существующую конфигурацию целиком. Сначала проверяется синтаксис, затем выполняется мягкая перезагрузка. Получение публичного сертификата зависит от DNS, доступности портов и условий центра сертификации.
gallery.example.com {
root * /srv/photoswipe/current/public
encode zstd gzip
file_server
}
# Проверка после добавления сайта в /etc/caddy/Caddyfile:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://gallery.example.com/
Приватные вложения: защита должна охватывать и изображения
Если галерея предназначена только для сотрудников, закрыть одну HTML-страницу недостаточно. Прямые адреса картинок, JSON-каталог и архивы тоже должны требовать авторизацию. Для небольшого внутреннего стенда можно использовать basic_auth на весь сайт в Caddy. Пароль не пишут открытым текстом в конфигурации: создаётся хеш, а сам доступ выполняется только по HTTPS.
Для клиентского кабинета с разными правами нужна авторизация в приложении. Сервер проверяет доступ к конкретному проекту при каждом запросе файла либо выдаёт ограниченную по времени подписанную ссылку. PhotoSwipe остаётся интерфейсом просмотра. Он не должен решать, кому принадлежит документ, и не способен сделать публичный URL приватным с помощью JavaScript.
caddy hash-password
# Внутри нужного блока сайта перед file_server:
# basic_auth {
# viewer <полученный_хеш>
# }
Кеш, обновление, откат и диагностика
Крупные изображения удобно публиковать под версионированными именами. Тогда новый файл получает новый адрес, а старый можно долго кешировать. HTML и JSON-каталог должны обновляться согласованно: иначе страница укажет на ещё не загруженные ресурсы. В нашем небольшом примере сложная политика кеширования не навязывается; сначала убедитесь, что все пути работают, затем настраивайте длительное хранение неизменяемых файлов.
Перед выпуском сохраните предыдущую папку releases и путь current. Обновление выполняется через временную ссылку и атомарное переименование. Для отката используется тот же механизм с предыдущим выпуском. Это не требует удаления всей галереи и позволяет быстро восстановить рабочую версию. Старые файлы удаляют позже по отдельной политике хранения, когда понятно, что на них больше нет актуальных ссылок.
sudo ln -s /srv/photoswipe/releases/20261108 /srv/photoswipe/current.next
sudo mv -Tf /srv/photoswipe/current.next /srv/photoswipe/current
# Откат: повторите с каталогом предыдущего выпуска.
sudo journalctl -u caddy -n 100 --no-pager
curl -I https://gallery.example.com/vendor/photoswipe.esm.js
Если галерея не открывается, начните с ошибок загрузки ES-модулей и MIME-типа JavaScript. Если картинка растянута — проверьте размеры в JSON. Если подпись не меняется — обработчик change и соответствие индекса текущей выборке. Если слайды дублируются — убедитесь, что старый экземпляр уничтожается перед новой инициализацией. Диагностика по конкретному симптому быстрее случайного изменения всех настроек.
Что перенести в собственный проект
Из мастерской можно взять три независимые части: структуру каталога, компонент просмотра и внешний интерфейс выбора. Для портфолио достаточно статического HTML и изображений. Для карточки заказа замените каталог на серверный ответ с проверкой прав. Для базы знаний сохраните подписи рядом с иллюстрациями. Для большого набора файлов добавьте пагинацию и ограничение объёма данных, не загружая тысячи записей заранее.
Перед переносом проверьте собственные изображения: размеры, ориентацию, формат, вес и текст альтернативного описания. Затем пройдите сценарий с клавиатурой и на телефоне. После этого подключайте аналитику, кеш и дополнительные кнопки. Такой порядок позволяет сначала получить понятный путь просмотра, а уже потом добавлять возможности, которые действительно нужны посетителям вашего сервиса.


