Галерея-слайдер с лайтбоксом для WordPress: пошаговый урок

от Михаил | Май 28, 2026 | Уроки

Что мы создаём

В этом уроке разберём готовый сниппет, который добавляет на страницы WordPress красивую галерею на основе Swiper.js с открытием фотографий в лайтбоксе. Особенность решения — оно работает только на страницах определённого типа записи, не нагружая остальные страницы сайта лишними скриптами.

Галерея-слайдер с лайтбоксом для WordPress

Что получится в итоге:

  • адаптивный слайдер с 1–3 колонками в зависимости от ширины экрана;
  • автопрокрутка с паузой при наведении;
  • открытие полноразмерного фото в лайтбоксе по клику;
  • навигация в лайтбоксе стрелками мыши и клавиатуры;
  • закрытие лайтбокса по клику на фон или клавише Escape;
  • шорткод работает только на страницах типа development.

Что понадобится

  • WordPress сайт
  • Плагин Advanced Custom Fields (ACF) — бесплатная версия подойдёт
  • Поле типа Gallery в ACF с именем gallery, привязанное к нужному типу записи
  • Доступ к файлу functions.php вашей темы (или возможность добавить сниппет через плагин, например Code Snippets)

Шаг 1. Создаём поле галереи в ACF

  1. Зайдите в ACF → Группы полей → Добавить новую.
  2. Назовите группу, например Галерея объекта.
  3. Добавьте поле:
    • Тип поля: Gallery
    • Имя поля: gallery (важно — именно так, строчными буквами)
  4. В разделе Правила отображения выберите: Тип записиравноdevelopment (или ваш тип записи).
  5. Сохраните группу.

Шаг 2. Добавляем сниппет в functions.php

Откройте файл functions.php вашей активной темы и вставьте код в конец файла. Если вы используете плагин Code Snippets — создайте новый сниппет и вставьте туда.

php

add_shortcode('custom_acf_gallery', 'display_acf_gallery_slider_lightbox');

function display_acf_gallery_slider_lightbox($atts) {
    // Работаем только на страницах типа 'development'
    if (!is_singular('development')) {
        return '';
    }

    $images = get_field('gallery');
    // ... остальной код сниппета
}

Важно: не редактируйте functions.php напрямую без резервной копии. Ошибка в этом файле может сделать сайт недоступным. Безопаснее использовать плагин Code Snippets.

Шаг 3. Разбираем код по частям

Регистрация шорткода

php

add_shortcode('custom_acf_gallery', 'display_acf_gallery_slider_lightbox');

Эта строка говорит WordPress: когда в контенте встретится — вызвать функцию display_acf_gallery_slider_lightbox и вставить её результат на место шорткода.

Ограничение по типу записи

php

if (!is_singular('development')) {
    return '';
}

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

Если у вас другой тип записи — замените 'development' на свой, например 'projects' или 'property'.

Получение изображений из ACF

php

$images = get_field('gallery');

get_field() — функция ACF, которая берёт данные поля gallery для текущей записи. Возвращает массив изображений, каждое из которых содержит:

  • $image['url'] — полный URL оригинала;
  • $image['sizes']['large'] — URL в размере large (обычно 1024px);
  • $image['alt'] — alt-текст изображения.

Уникальный ID слайдера

php

$slider_id = 'swiper-' . uniqid();

uniqid() генерирует уникальную строку на основе времени. Это позволяет безопасно использовать шорткод несколько раз на одной странице — каждый слайдер получит свой ID и не будет конфликтовать с другими.

Подключение стилей Swiper

php

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />

Стили Swiper подключаются через CDN прямо в выводе шорткода. Это простое решение, но если на странице несколько галерей — стили подключатся несколько раз. Для продакшн-сайта лучше вынести подключение в wp_enqueue_styles.

HTML-структура слайдера

php

<div id="swiper-xxxx" class="swiper">
    <div class="swiper-wrapper">
        <div class="swiper-slide" onclick="...">
            <img src="..." alt="..." />
        </div>
    </div>
    <div class="swiper-pagination"></div>
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>
</div>

Это стандартная структура Swiper.js. Каждый слайд — это одно изображение из галереи ACF. На каждый слайд вешается обработчик onclick, который открывает лайтбокс с нужным индексом.

Инициализация Swiper

javascript

const swiper = new Swiper("#swiper-xxxx", {
    loop: true,
    speed: 600,
    grabCursor: true,
    autoplay: { delay: 3000, disableOnInteraction: false, pauseOnMouseEnter: true },
    pagination: { el: ".swiper-pagination", clickable: true },
    navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev" },
    breakpoints: {
        320: { slidesPerView: 1, spaceBetween: 15 },
        768: { slidesPerView: 2, spaceBetween: 20 },
        1024: { slidesPerView: 3, spaceBetween: 30 }
    }
});

Ключевые параметры:

  • loop: true — бесконечная прокрутка;
  • autoplay — автопрокрутка каждые 3 секунды, останавливается при наведении мыши;
  • breakpoints — адаптив: 1 слайд на мобильных, 2 на планшетах, 3 на десктопе.

Лайтбокс — как это работает

Все URL оригинальных изображений сохраняются в глобальный объект window.acfGalleries:

javascript

window.acfGalleries["swiper-xxxx"] = ["url1.jpg", "url2.jpg", ...];

При клике на слайд вызывается openCustomLightbox(index, galId), которая запоминает текущую галерею и индекс фото, затем показывает лайтбокс.

HTML лайтбокса создаётся один раз и вставляется в конец <body>, даже если на странице несколько галерей:

javascript

if (!document.getElementById("custom-vanilla-lightbox")) {
    // создаём лайтбокс только один раз
}

Навигация по лайтбоксу:

  • Стрелки на экране — клик по cvl-prev / cvl-next;
  • Клавиатура — стрелки влево/вправо, Escape для закрытия;
  • Клик на фон — закрывает лайтбокс.

Шаг 4. Вставляем шорткод на страницу

После добавления кода в functions.php откройте редактор любой записи типа development и вставьте шорткод:

[custom_acf_gallery]

Не забудьте загрузить изображения в поле Gallery этой записи через ACF.

Шаг 5. Настройка под свой проект

Изменить тип записи

Замените 'development' на нужный тип в двух местах:

php

if (!is_singular('development')) {

Изменить имя поля ACF

Если ваше поле называется иначе — замените 'gallery':

php

$images = get_field('your_field_name');

Изменить количество слайдов

Отредактируйте breakpoints в инициализации Swiper:

javascript

breakpoints: {
    320: { slidesPerView: 1, spaceBetween: 15 },
    768: { slidesPerView: 3, spaceBetween: 20 },  // 3 на планшете
    1024: { slidesPerView: 4, spaceBetween: 30 }  // 4 на десктопе
}

Отключить автопрокрутку

Удалите или закомментируйте строку autoplay:

javascript

// autoplay: { delay: 3000, disableOnInteraction: false, pauseOnMouseEnter: true },

Изменить соотношение сторон изображений

Найдите в CSS:

css

aspect-ratio: 4/3;

И замените на нужное, например 16/9 или 1/1.

Возможные проблемы

Галерея не отображается Убедитесь, что поле ACF называется именно gallery и в него загружены изображения для данной записи.

Шорткод показывает текст Код не был добавлен в functions.php, либо в нём синтаксическая ошибка. Проверьте через плагин Health Check или посмотрите логи PHP.

Лайтбокс не открывается Откройте консоль браузера (F12) и проверьте ошибки JavaScript. Возможен конфликт с другим плагином, который переопределяет window.openCustomLightbox.

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

Итог

Мы разобрали сниппет, который без сторонних плагинов галерей добавляет полноценный слайдер с лайтбоксом на WordPress. Решение легковесное — используются только Swiper.js с CDN и нативный JavaScript без jQuery. Ограничение по типу записи гарантирует, что лишние скрипты не загружаются на других страницах сайта.

Полный код сниппета можно скопировать из начала этой статьи и адаптировать под свой проект, изменив название типа записи и поля ACF.

Весь код сниппета целиком

add_shortcode('custom_acf_gallery', 'display_acf_gallery_slider_lightbox');

function display_acf_gallery_slider_lightbox($atts) {
// Выполняем только на страницах с типом записи 'development'
if (!is_singular('development')) {
return '';
}
$images = get_field('gallery'); 

if( $images ):
    $slider_id = 'swiper-' . uniqid();

    $image_urls = [];

    // 1. СТИЛИ (Swiper + Lightbox)
    $output = '
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
    <style>
        /* --- Стили Слайдера --- */
        #' . $slider_id . ' { width: 100%; padding-bottom: 40px; }
        #' . $slider_id . ' .swiper-slide { border-radius: 8px; overflow: hidden; cursor: zoom-in; }
        #' . $slider_id . ' .swiper-slide img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; }

        #' . $slider_id . ' .swiper-button-next,
        #' . $slider_id . ' .swiper-button-prev { color: #ffffff; text-shadow: 0 2px 6px rgba(0,0,0,0.4); transition: transform 0.3s ease, opacity 0.3s; }
        #' . $slider_id . ' .swiper-button-next:hover { transform: translateX(3px); }
        #' . $slider_id . ' .swiper-button-prev:hover { transform: translateX(-3px); }
        #' . $slider_id . ' .swiper-button-next:after,
        #' . $slider_id . ' .swiper-button-prev:after { font-size: 24px !important; font-weight: 300; }

        #' . $slider_id . ' .swiper-pagination-bullet { width: 8px; height: 8px; background-color: #bbbbbb; opacity: 0.6; transition: all 0.3s ease; }
        #' . $slider_id . ' .swiper-pagination-bullet:hover { opacity: 1; }
        #' . $slider_id . ' .swiper-pagination-bullet-active { width: 24px; border-radius: 4px; background-color: #333333; opacity: 1; }

        /* --- Стили Лайтбокса --- */
        #custom-vanilla-lightbox { display: none; position: fixed; z-index: 999999; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.9); align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease; }
        #custom-vanilla-lightbox.active { display: flex; opacity: 1; }
        #custom-vanilla-lightbox img { max-width: 90%; max-height: 90%; border-radius: 4px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); object-fit: contain; }
        .cvl-close { position: absolute; top: 20px; right: 30px; color: #fff; font-size: 40px; font-weight: bold; cursor: pointer; user-select: none; transition: color 0.2s; z-index: 10; }
        .cvl-close:hover { color: #bbb; }
        .cvl-nav { position: absolute; top: 50%; transform: translateY(-50%); color: #fff; font-size: 50px; font-weight: bold; cursor: pointer; user-select: none; padding: 20px; transition: color 0.2s; z-index: 10; }
        .cvl-nav:hover { color: #bbb; }
        .cvl-prev { left: 20px; }
        .cvl-next { right: 20px; }
    </style>';

    // 2. HTML СЛАЙДЕРА
    $output .= '<div id="' . $slider_id . '" class="swiper">';
    $output .= '<div class="swiper-wrapper">';

    foreach( $images as $index => $image ):
        $image_urls[] = esc_url($image['url']);

        $output .= '<div class="swiper-slide" onclick="window.openCustomLightbox(' . $index . ', \'' . $slider_id . '\')">';
        $output .= '<img src="' . esc_url($image['sizes']['large']) . '" alt="' . esc_attr($image['alt']) . '" />';
        $output .= '</div>';
    endforeach;

    $output .= '</div>'; // swiper-wrapper

    $output .= '<div class="swiper-pagination"></div>';
    $output .= '<div class="swiper-button-prev"></div>';
    $output .= '<div class="swiper-button-next"></div>';
    $output .= '</div>'; // swiper

    $json_urls = json_encode($image_urls);

    // 3. СКРИПТЫ (Swiper + Логика Лайтбокса)
    $output .= '
    <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
    <script>
        document.addEventListener("DOMContentLoaded", function() {
            // --- Инициализация Swiper ---
            const swiper = new Swiper("#' . $slider_id . '", {
                loop: true,
                speed: 600,
                grabCursor: true,
                autoplay: { delay: 3000, disableOnInteraction: false, pauseOnMouseEnter: true },
                pagination: { el: ".swiper-pagination", clickable: true },
                navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev" },
                breakpoints: {
                    320: { slidesPerView: 1, spaceBetween: 15 },
                    768: { slidesPerView: 2, spaceBetween: 20 },
                    1024: { slidesPerView: 3, spaceBetween: 30 }
                }
            });

            // --- Инициализация данных для Лайтбокса ---
            if (!document.getElementById("custom-vanilla-lightbox")) {
                const lbHtml = `
                    <div id="custom-vanilla-lightbox">
                        <span class="cvl-close" onclick="window.closeCustomLightbox()">&times;</span>
                        <span class="cvl-nav cvl-prev" onclick="window.changeCustomLightbox(-1)">&#10094;</span>
                        <img id="cvl-image" src="" alt="">
                        <span class="cvl-nav cvl-next" onclick="window.changeCustomLightbox(1)">&#10095;</span>
                    </div>
                `;
                document.body.insertAdjacentHTML("beforeend", lbHtml);
            }

            if (typeof window.acfGalleries === "undefined") {
                window.acfGalleries = {};
            }
            window.acfGalleries["' . $slider_id . '"] = ' . $json_urls . ';

            if (typeof window.openCustomLightbox !== "function") {
                window.currentLightboxIndex = 0;
                window.currentLightboxGallery = "";

                window.openCustomLightbox = function(index, galId) {
                    window.currentLightboxIndex = index;
                    window.currentLightboxGallery = galId;
                    window.updateLightboxImage();
                    const lb = document.getElementById("custom-vanilla-lightbox");
                    lb.style.display = "flex";
                    setTimeout(() => { lb.classList.add("active"); }, 10);
                    document.body.style.overflow = "hidden";
                };

                window.closeCustomLightbox = function() {
                    const lb = document.getElementById("custom-vanilla-lightbox");
                    lb.classList.remove("active");
                    setTimeout(() => { lb.style.display = "none"; }, 300);
                    document.body.style.overflow = "";
                };

                window.changeCustomLightbox = function(step) {
                    const images = window.acfGalleries[window.currentLightboxGallery];
                    window.currentLightboxIndex += step;
                    if (window.currentLightboxIndex >= images.length) window.currentLightboxIndex = 0;
                    else if (window.currentLightboxIndex < 0) window.currentLightboxIndex = images.length - 1;
                    window.updateLightboxImage();
                };

                window.updateLightboxImage = function() {
                    const images = window.acfGalleries[window.currentLightboxGallery];
                    document.getElementById("cvl-image").src = images[window.currentLightboxIndex];
                };

                const lbElem = document.getElementById("custom-vanilla-lightbox");
                lbElem.addEventListener("click", function(e) {
                    if (e.target === this) window.closeCustomLightbox();
                });

                document.addEventListener("keydown", function(e) {
                    const lbIsActive = document.getElementById("custom-vanilla-lightbox").classList.contains("active");
                    if (!lbIsActive) return;
                    if (e.key === "Escape") window.closeCustomLightbox();
                    else if (e.key === "ArrowRight") window.changeCustomLightbox(1);
                    else if (e.key === "ArrowLeft") window.changeCustomLightbox(-1);
                });
            }
        });
    </script>';

    return $output;
endif;

return '';
}

Было полезно?

Пожалуйста, расскажите об этом друзьям!

VK
Pinterest
OK
Telegram
Linkedin
WhatsApp
Viber
Reddit

* Meta / Facebook — сервисы, предоставляемые организацией, признанной экстремистской

Готовы получать больше клиентов?

Ваш сайт может быть не просто визиткой, а полноценным инструментом продаж — работать 24/7, привлекать заявки и усиливать доверие к вашему бизнесу. Оставьте заявку — и мы подскажем, какое решение подойдёт именно вам.

Вам может быть интересно

Telegram Почта info@pureseo.ru Телефон +7 (903) 757-15-01