Налаштування галереї зображень товара (swiper/slider) у 1С-Бітрікс
Стандартний шаблон catalog.element у Бітріксі рендерит додаткові зображення товара (MORE_PHOTO) як набір тегів <img> без будь-якої галереї логіки. Магазин підключає Swiper, галерея працює на головній сторінці, але в карточці товара слайдер ініціалізується до того, як компонент відав HTML — і отримує порожній контейнер. Це класична проблема порядку виконання скриптів у Бітріксі.
Дані зображень у компоненті catalog.element
Компонент збирає всі зображення товара в $arResult['MORE_PHOTO'] — масив шляхів до вже ресайзених картинок. Оригіналі зберігаються в b_iblock_element.DETAIL_PICTURE та властивості MORE_PHOTO (тип F, множественное). Для слайдера зазвичай потрібні два розміри: мініатюра для превью-смуги та повнорозмірна для основного слайду.
У шаблоні template.php компонента:
<?php
$slides = [];
foreach ($arResult['PROPERTIES']['MORE_PHOTO']['FILE_VALUE'] as $fileArr) {
$thumb = \CFile::ResizeImageGet($fileArr['ID'], ['width' => 80, 'height' => 80], BX_RESIZE_IMAGE_PROPORTIONAL);
$full = \CFile::ResizeImageGet($fileArr['ID'], ['width' => 800, 'height' => 800], BX_RESIZE_IMAGE_PROPORTIONAL);
$slides[] = [
'thumb' => $thumb['src'],
'full' => $full['src'],
'alt' => htmlspecialcharsEx($fileArr['DESCRIPTION'] ?: $arResult['NAME']),
];
}
?>
Розмітка для Swiper
Swiper очікує строгу структуру .swiper > .swiper-wrapper > .swiper-slide. Будь-яке відхилення — і бібліотека не знайде слайди. Основний слайдер та слайдер мініатюр — два окремі екземпляри Swiper, пов'язані через параметр thumbs.swiper:
<div class="swiper product-main-swiper" id="productMainSwiper">
<div class="swiper-wrapper">
<?php foreach ($slides as $slide): ?>
<div class="swiper-slide">
<img src="<?= $slide['full'] ?>" alt="<?= $slide['alt'] ?>" loading="lazy">
</div>
<?php endforeach; ?>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<div class="swiper product-thumbs-swiper" id="productThumbsSwiper">
<div class="swiper-wrapper">
<?php foreach ($slides as $slide): ?>
<div class="swiper-slide">
<img src="<?= $slide['thumb'] ?>" alt="" loading="lazy">
</div>
<?php endforeach; ?>
</div>
</div>
Ініціалізація та порядок скриптів
Ключова проблема Бітрікса: $APPLICATION->AddHeadScript() додає скрипти в <head>, а компонент рендерится пізніше в <body>. Swiper підключений в head, але new Swiper() викликається в inline-скрипті шаблону — DOM ще не готів.
Правильне рішення — відкладена ініціалізація через DOMContentLoaded або через пролог/епілог. У шаблоні компонента:
document.addEventListener('DOMContentLoaded', function () {
const thumbsSwiper = new Swiper('#productThumbsSwiper', {
slidesPerView: 4,
spaceBetween: 8,
watchSlidesProgress: true,
});
new Swiper('#productMainSwiper', {
spaceBetween: 0,
thumbs: { swiper: thumbsSwiper },
keyboard: { enabled: true },
});
});
Lazy loading та LCP
loading="lazy" на першому слайді убиває LCP — браузер відкладає завантаження головного зображення товара. Перший слайд повинен грузитися без lazy:
foreach ($slides as $i => $slide):
$loading = $i === 0 ? 'eager' : 'lazy';
Також варто додати fetchpriority="high" на перший слайд — це підказка браузеру підвищити приоритет запросу.
Зміна зображень при виборі SKU
Коли користувач вибирає торгове пропозицію, Бітрікс через AJAX оновлює блок ціни та наявності. Галерея при цьому не змінюється — вона прив'язана до батьківського елемента. Щоб синхронізувати: слухати подію onSaleComponentOfferSelect (стандартна подія Бітрікса), отримувати offerId, запитувати фото пропозиції через користувацький AJAX-екшн та пересоздавати слайдер з новими даними через swiper.destroy() + реініціалізацію.







