Создание галереи с лайтбоксом на WordPress с помощью ACF
Интерактивная галерея превращает набор фотографий в удобный просмотр: миниатюры занимают компактную сетку, а выбранный снимок открывается поверх страницы. Пользователь изучает изображения без перехода на отдельные вложения и сохраняет контекст материала.
С помощью ACF удобно хранить ссылки на изображения, подписи и альтернативные тексты рядом с записью. Расширенные пользовательские поля отделяют данные от темы, поэтому галерею можно вывести в любом шаблоне и менять разметку без ручного редактирования HTML.
В примере используется поле Repeater, нативный элемент dialog и небольшой скрипт на современном JavaScript. Получится адаптивная галерея с полноразмерным просмотром, закрытием по Escape, возвратом фокуса и корректными подписями.
Подготовка WordPress и расширений
Установите расширение Advanced Custom Fields и активируйте лицензию Pro: для поля Repeater требуется расширенная версия. Обновляйте WordPress, PHP и плагины, а перед изменениями сделайте резервную копию сайта и базы данных.
Создайте дочернюю тему, если основная тема обновляется автоматически. В ней подготовьте каталоги assets/css и assets/js, а затем подключите gallery.css через wp_enqueue_style, а gallery.js через wp_enqueue_script. Файлы родительской темы лучше не изменять, иначе правки могут исчезнуть при обновлении.
Для базовой проверки установленной сборки полезны материалы по WordPress: начните с резервной копии, последовательно активируйте плагины и убедитесь, что сайт открывается без ошибок. Так вы исключите конфликт расширений ещё до начала разработки галереи.
Поля ACF для изображений
В панели ACF откройте раздел групп полей и создайте группу «Галерея». Привяжите её к нужному типу публикации или выберите правило отображения для отдельных страниц. Поле Repeater назовите gallery_images, чтобы его имя совпадало с будущим шаблоном.
Внутри Repeater добавьте подполе image типа Image с источником «Медиатека». В качестве возвращаемого значения выберите ID изображения: WordPress сможет определить актуальный адрес файла и сформировать миниатюру нужного размера. Для ручной подписи создайте текстовое подполе caption.
Альтернативный текст удобно задавать непосредственно в карточке вложения. Шаблон возьмёт его из поля _wp_attachment_image_alt, а при отсутствии использует подпись или название файла. Так изображение получит осмысленное имя для программ экранного доступа.
Шаблон вывода галереи
В дочерней теме создайте файл gallery-template.php и вызовите его из нужного шаблона страницы командой get_template_part( 'gallery-template' ). Внутри файла переберите строки Repeater, получите ID изображения, подпись и адрес полноразмерной версии.
<?php
if ( have_rows( 'gallery_images' ) ) :
?>
<div class="acf-gallery" data-acf-gallery>
<?php
while ( have_rows( 'gallery_images' ) ) :
$image_id = (int) get_sub_field( 'image' );
$caption = (string) get_sub_field( 'caption' );
$alt = get_post_meta( $image_id, '_wp_attachment_image_alt', true );
if ( ! $alt ) {
$alt = $caption ? $caption : get_the_title( $image_id );
}
$full = wp_get_attachment_image_src( $image_id, 'full' );
if ( ! $full ) {
continue;
}
?>
<button
type="button"
class="acf-gallery__item"
data-lightbox-open
data-full="<?php echo esc_url( $full[0] ); ?>"
data-alt="<?php echo esc_attr( $alt ); ?>"
data-caption="<?php echo esc_attr( $caption ); ?>"
aria-haspopup="dialog"
>
<?php
echo wp_get_attachment_image(
$image_id,
'large',
false,
array(
'alt' => $alt,
'loading' => 'lazy',
'decoding' => 'async',
)
);
?>
</button>
<?php endwhile; ?>
<dialog
class="acf-lightbox"
data-lightbox-dialog
aria-label="Просмотр изображения"
>
<button type="button" class="acf-lightbox__close" data-lightbox-close>
Закрыть
</button>
<img class="acf-lightbox__image" data-lightbox-image alt="">
<p class="acf-lightbox__caption" data-lightbox-caption></p>
</dialog>
</div>
<?php endif; ?>
Кнопка хранит полный адрес в атрибуте data-full, но не загружает тяжёлый оригинал вместе со страницей. Подпись и альтернативный текст выводятся с экранированием, поэтому значения из медиатеки не попадут в HTML как произвольная разметка.
Функция wp_get_attachment_image формирует оптимизированный тег с поддержкой srcset. Для миниатюр можно использовать размер large, а для модального окна — отдельную полноразмерную копию без изменения оригинала.
Скрипт модального окна
Скрипт находит каждую галерею и навешивает обработчик на её кнопки. При нажатии он переносит адрес, подпись и альтернативный текст в нативный dialog, после чего вызывает showModal(). Библиотека jQuery для этого решения не требуется.
document.querySelectorAll('[data-acf-gallery]').forEach((gallery) => {
const dialog = gallery.querySelector('[data-lightbox-dialog]');
const image = gallery.querySelector('[data-lightbox-image]');
const caption = gallery.querySelector('[data-lightbox-caption]');
const closeButton = gallery.querySelector('[data-lightbox-close]');
let activeTrigger = null;
gallery.querySelectorAll('[data-lightbox-open]').forEach((button) => {
button.addEventListener('click', () => {
activeTrigger = button;
image.src = button.dataset.full;
image.alt = button.dataset.alt || '';
caption.textContent = button.dataset.caption || '';
document.body.classList.add('acf-lightbox-open');
dialog.showModal();
closeButton.focus();
});
});
closeButton.addEventListener('click', () => {
dialog.close();
});
dialog.addEventListener('click', (event) => {
if (event.target === dialog) {
dialog.close();
}
});
dialog.addEventListener('close', () => {
document.body.classList.remove('acf-lightbox-open');
image.removeAttribute('src');
caption.textContent = '';
if (activeTrigger) {
activeTrigger.focus();
}
});
});
Нативный dialog размещается в верхнем слое браузера, поэтому ему не требуется ручная настройка z-index. Клавиша Escape закрывает окно, а событие close возвращает фокус исходной кнопке. Щелчок по затемнённому фону также завершает просмотр.
Оформление и адаптивность
Сетку можно задать через CSS Grid: она автоматически перестроится при изменении ширины экрана. Для миниатюр полезно сохранять одинаковое соотношение сторон, а полноразмерное изображение показывать через object-fit: contain, чтобы оно не обрезалось.
.acf-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
}
.acf-gallery__item {
display: block;
width: 100%;
padding: 0;
overflow: hidden;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 8px;
background: transparent;
cursor: zoom-in;
}
.acf-gallery__item img {
display: block;
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
}
.acf-gallery__item:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 3px;
}
.acf-lightbox {
width: min(92vw, 1200px);
max-width: none;
max-height: 92vh;
padding: 1rem;
border: 0;
background: #111;
color: #fff;
}
.acf-lightbox[open] {
display: grid;
gap: 0.75rem;
}
.acf-lightbox__image {
display: block;
max-width: 100%;
max-height: 76vh;
margin: auto;
object-fit: contain;
}
.acf-lightbox__close {
justify-self: end;
padding: 0.5rem 0.8rem;
cursor: pointer;
}
.acf-lightbox__caption {
margin: 0;
text-align: center;
}
.acf-lightbox__caption:empty {
display: none;
}
.acf-lightbox::backdrop {
background: rgba(0, 0, 0, 0.82);
}
.acf-lightbox-open {
overflow: hidden;
}
@media (max-width: 600px) {
.acf-gallery {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.5rem;
}
.acf-lightbox {
width: 96vw;
}
}
Перед загрузкой подготовьте облегчённую версию для сетки и сохраните отдельный оригинал для модального окна. WordPress может создавать WebP или AVIF, если соответствующие форматы поддерживаются сервером. Для фотографий, полученных со сканера, параметры обработки можно уточнить в программе Nikon Coolscan.
Проверка, доступность и публикация
Проверьте страницу на тестовом сервере с разным количеством изображений, разными пропорциями и разрешениями. Посмотрите галерею на узком экране, обычном мониторе и Retina-дисплее. Убедитесь, что страница сохраняет работоспособность при отключённом JavaScript: миниатюры должны оставаться доступными.
Проверьте навигацию с клавиатуры. Кнопки должны получать заметное состояние фокуса, Enter открывать снимок, Escape закрывать окно, а фокус после закрытия возвращаться к выбранному изображению. Убедитесь, что альтернативные тексты не пусты, подписи читаются, а контраст кнопки закрытия соответствует фону.
Перед публикацией откройте страницу в отдельном профиле браузера и оцените защиту Edge от трекеров: внешние счётчики, шрифты и рекламные скрипты могут менять поведение страницы и увеличивать объём передаваемых данных. Проверьте защищённое соединение, актуальность плагинов, журнал ошибок и работу с минифицированными файлами.
Готовый модуль хранит данные в ACF, а оформление и поведение остаются в дочерней теме. Такое разделение упрощает перенос решения, позволяет менять сетку независимо от записей и сохранять галерею при обновлении WordPress.
Создайте черновик страницы, привяжите к нему группу полей, загрузите снимки и проверьте результат в мобильном и настольном режимах. После успешной проверки перенесите готовые файлы в дочернюю тему, сохраните настройки группы ACF и опубликуйте страницу — галерея будет готова к использованию на сайте.