Lightbox на чистому JavaScript без зовнішніх залежностей забезпечує сайту потрібну швидкість і стабільність яку вимагають сучасні мобільні технології, про що також наголошує PageSpeed

Чистий і сучасний Lightbox без зовнішніх залежностей забезпечує нам потрібну швидкість і стабільність. Для прикладу візьмемо код шаблону модуля зображень в Joomla:

<?php

// Отримуємо об'єкт документа через Factory (універсальний спосіб для Joomla 6)
$doc = Factory::getApplication()->getDocument();

// Формуємо стилі
$style = "
.usegall-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax({$params->get('width', 150)}px, 1fr)); gap: 15px; }
.usegall-item img { width: 100%; height: auto; border-radius: 8px; transition: 0.3s; object-fit: cover; border: 1px solid #ddd; }
.usegall-item img:hover { transform: scale(1.05); cursor: pointer; box-shadow: 0 4px 10px rgba(0,0,0,0.2); }
.lightbox-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.9); display:none; justify-content:center; align-items:center; z-index:10000; cursor: pointer; }
.lightbox-overlay img { max-width: 90%; max-height: 90%; border: 3px solid #fff; box-shadow: 0 0 20px rgba(0,0,0,0.5); }
";

// Додаємо стилі в <head> через об'єкт $doc
$doc->addStyleDeclaration($style);
?>

<div class="mod-usegall">
<div class="usegall-grid">
<?php foreach ($images as $img) : ?>
<?php $src = $img->folder . '/' . htmlspecialchars($img->name, ENT_COMPAT, 'UTF-8'); ?>
<div class="usegall-item">
<img src="/<?php echo $src; ?>"
alt="<?php echo htmlspecialchars($img->name); ?>"
onclick="openLightbox(this.src)"
width="<?php echo $params->get('width'); ?>"
height="<?php echo $params->get('height', 'auto'); ?>">
</div>
<?php endforeach; ?>
</div>
</div>

<div id="usegall-overlay" class="lightbox-overlay" onclick="this.style.display='none'">
<img id="usegall-full-img" src="/" alt="Збільшене фото">
</div>

<script>
function openLightbox(src) {
const overlay = document.getElementById('usegall-overlay');
const fullImg = document.getElementById('usegall-full-img');
fullImg.src = src;
overlay.style.display = 'flex';
}
</script>

Для того, щоб додати можливість гортати зображення, нам потрібно перетворити простий перегляд на повноцінний слайдер. Оскільки ми домовилися використовувати чистий JS (Vanilla JS), ми розширимо наш скрипт: додамо масив усіх зображень та відстеження поточного індексу.

<?php

// Додаємо стилі для сітки та кнопок гортання
$style = "
.usegall-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax({$params->get('width', 150)}px, 1fr)); gap: 15px; }
.usegall-item img { width: 100%; height: auto; border-radius: 8px; transition: 0.3s; object-fit: cover; cursor: pointer; }
.usegall-item img:hover { transform: scale(1.05); }.lightbox-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.9); display:none; justify-content:center; align-items:center; z-index:10000; }
.lightbox-overlay img { max-width: 85%; max-height: 85%; border: 3px solid #fff; user-select: none; }.lb-nav { position: absolute; top: 50%; width: 100%; display: flex; justify-content: space-between; padding: 0 20px; transform: translateY(-50%); pointer-events: none; }
.lb-btn { background: rgba(255,255,255,0.2); color: white; border: none; font-size: 40px; padding: 10px 20px; cursor: pointer; pointer-events: auto; transition: 0.3s; border-radius: 5px; }
.lb-btn:hover { background: rgba(255,255,255,0.5); }
.lb-close { position: absolute; top: 20px; right: 20px; color: white; font-size: 30px; cursor: pointer; background: none; border: none; }
";

$doc->addStyleDeclaration($style);

// Підготуємо масив шляхів для JavaScript
$jsImages = [];
foreach ($images as $img) {
$jsImages[] = $img->folder . '/' . htmlspecialchars($img->name, ENT_COMPAT, 'UTF-8');
}
?>

<div class="mod-usegall">
<div class="usegall-grid">
<?php foreach ($images as $index => $img) : ?>
<?php $src = $img->folder . '/' . htmlspecialchars($img->name, ENT_COMPAT, 'UTF-8'); ?>
<div class="usegall-item">
<img src="/<?php echo $src; ?>"
onclick="openLightbox(<?php echo $index; ?>)"
width="<?php echo $params->get('width'); ?>"
height="<?php echo $params->get('height', 'auto'); ?>">
</div>
<?php endforeach; ?>
</div>
</div>

<div id="usegall-overlay" class="lightbox-overlay">
<button class="lb-close" onclick="closeLightbox()">&times;</button>
<div class="lb-nav">
<button class="lb-btn" onclick="prevImg()">&#10094;</button>
<button class="lb-btn" onclick="nextImg()">&#10095;</button>
</div>
<img id="usegall-full-img" src="/" alt="Gallery image">
</div>

<script>
// Передаємо масив зображень з PHP в JS
const galleryImages = <?php echo json_encode($jsImages); ?>;
let currentIndex = 0;

function openLightbox(index) {
currentIndex = index;
updateImage();
document.getElementById('usegall-overlay').style.display = 'flex';
}

function closeLightbox() {
document.getElementById('usegall-overlay').style.display = 'none';
}

function updateImage() {
const fullImg = document.getElementById('usegall-full-img');
fullImg.src = galleryImages[currentIndex];
}

function nextImg() {
currentIndex = (currentIndex + 1) % galleryImages.length;
updateImage();
}

function prevImg() {
currentIndex = (currentIndex - 1 + galleryImages.length) % galleryImages.length;
updateImage();
}

// Додамо керування клавішами (стрілки вліво/вправо та Esc)
document.addEventListener('keydown', function(e) {
if (document.getElementById('usegall-overlay').style.display === 'flex') {
if (e.key === 'ArrowRight') nextImg();
if (e.key === 'ArrowLeft') prevImg();
if (e.key === 'Escape') closeLightbox();
}
});

// Закриття при кліку на фон (але не на картинку чи кнопки)
document.getElementById('usegall-overlay').addEventListener('click', function(e) {
if (e.target === this) closeLightbox();
});
</script>

Додатково про Lightbox на чистому JavaScript:

  1. Логіка індексів: Тепер кожна картинка в циклі отримує свій $index. При натисканні функція openLightbox запам'ятовує, яке саме фото відкрите.
  2. JS Масив: Ми використали json_encode($jsImages), щоб перетворити список шляхів з PHP у масив, який розуміє браузер (JavaScript).
  3. Кнопки навігації:
    • &#10094; (❮) та &#10095; (❯) — це HTML-коди для стрілок.
    • Функції nextImg та prevImg дозволяють гортати фото по колу (після останнього знову йде перше).
  4. Керування клавіатурою: Для зручності користувача я додав обробник keydown. Тепер можна гортати фото стрілками на клавіатурі або закрити галерею клавішею Esc.
  5. Покращений UX: Клік по темному фону за межами картинки тепер теж закриває попап.

Це рішення ідеально підходить для сайту: воно легке, працює без затримок на мобільних пристроях і не потребує завантаження "важких" плагінів.