c18-图片灯箱组件 Image Lightbox | 100行代码实现点击放大,比插件轻100倍
Web Component Dictionary v2.0 · 网页组件活字典 83个组件 / 8大分类 / 中英双语 / 实时预览 / 单文件无依赖 在线体验 | 购买 ¥9.99
你的产品页有10张截图,用户想看大图细节——不需要引入一个50KB的Lightbox插件。100行原生JS,支持缩略图点击、键盘导航、手势关闭,比任何库都干净。
组件是什么
Image Lightbox(图片灯箱)在用户点击缩略图时,覆盖一个全屏遮罩层展示原图。核心功能:打开/关闭动画、键盘ESC关闭、点击遮罩关闭、移动端手势支持。
HTML结构
<!-- 缩略图网格 -->
<div class="gallery">
<img src="thumbnail-1.jpg" data-full="full-1.jpg"
onclick="openLightbox(this)" alt="Screenshot 1">
<img src="thumbnail-2.jpg" data-full="full-2.jpg"
onclick="openLightbox(this)" alt="Screenshot 2">
<img src="thumbnail-3.jpg" data-full="full-3.jpg"
onclick="openLightbox(this)" alt="Screenshot 3">
</div>
<!-- 灯箱遮罩 -->
<div id="lightbox" class="lightbox" onclick="closeLightbox()">
<span class="lb-close">×</span>
<button class="lb-prev" onclick="event.stopPropagation();navigateLightbox(-1)">‹</button>
<img id="lb-img" class="lb-img" src="" alt="">
<button class="lb-next" onclick="event.stopPropagation();navigateLightbox(1)">›</button>
<p class="lb-caption" id="lb-caption"></p>
</div>
CSS核心
.lightbox {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0, 0, 0, 0.92);
z-index: 9999;
align-items: center;
justify-content: center;
flex-direction: column;
}
.lightbox.active {
display: flex;
}
.lb-img {
max-width: 90%;
max-height: 80vh;
border-radius: 8px;
transition: transform 0.3s ease;
}
.lb-prev, .lb-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255,255,255,0.15);
color: #fff;
border: none;
font-size: 36px;
padding: 12px 18px;
cursor: pointer;
border-radius: 4px;
}
.lb-prev { left: 20px; }
.lb-next { right: 20px; }
.lb-close {
position: absolute;
top: 20px;
right: 30px;
font-size: 40px;
color: #fff;
cursor: pointer;
}
.lb-caption {
color: #fff;
margin-top: 16px;
font-size: 14px;
}
JavaScript核心
let currentImages = [];
let currentIndex = 0;
function openLightbox(img) {
// 收集所有可导航的图片
currentImages = Array.from(document.querySelectorAll('.gallery img'));
currentIndex = currentImages.indexOf(img);
updateLightboxImage();
const lb = document.getElementById('lightbox');
lb.classList.add('active');
document.body.style.overflow = 'hidden'; // 禁止背景滚动
}
function updateLightboxImage() {
const img = currentImages[currentIndex];
document.getElementById('lb-img').src = img.dataset.full || img.src;
document.getElementById('lb-caption').textContent = img.alt || '';
}
function closeLightbox() {
document.getElementById('lightbox').classList.remove('active');
document.body.style.overflow = '';
}
function navigateLightbox(direction) {
currentIndex = (currentIndex + direction + currentImages.length) % currentImages.length;
updateLightboxImage();
}
// 键盘导航
document.addEventListener('keydown', (e) => {
const lb = document.getElementById('lightbox');
if (!lb.classList.contains('active')) return;
if (e.key === 'Escape') closeLightbox();
if (e.key === 'ArrowLeft') navigateLightbox(-1);
if (e.key === 'ArrowRight') navigateLightbox(1);
});
移动端手势
let touchStartX = 0;
document.getElementById('lightbox').addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
});
document.getElementById('lightbox').addEventListener('touchend', (e) => {
const diff = touchStartX - e.changedTouches[0].clientX;
if (Math.abs(diff) > 50) {
navigateLightbox(diff > 0 ? 1 : -1); // 左滑=下一张,右滑=上一张
}
});
渐进式加载:先用缩略图占位
function updateLightboxImage() {
const img = currentImages[currentIndex];
const lbImg = document.getElementById('lb-img');
// 先用缩略图快速显示,然后替换为高清图
lbImg.src = img.src;
const fullSrc = img.dataset.full;
if (fullSrc && fullSrc !== img.src) {
const hdImg = new Image();
hdImg.onload = () => { lbImg.src = fullSrc; };
hdImg.src = fullSrc;
}
}
为什么不用插件
| 方案 | 体积 | 依赖 | 自定义 |
|---|---|---|---|
| Lightbox2 | 50KB+ | jQuery | 受限 |
| Fancybox | 80KB+ | 无 | 中等 |
| 原生实现 | <2KB | 0 | 完全自由 |
100行原生JS覆盖90%使用场景,剩下10%的边角需求不值得引入一个第三方依赖。
Image Lightbox: 100 Lines of Vanilla JS, 100x Lighter Than Any Plugin
Your product page has 10 screenshots. Users want to see details — no need for a 50KB Lightbox plugin. 100 lines of vanilla JS handles thumbnail clicks, keyboard nav, and swipe gestures.
What It Is
A fullscreen overlay triggered by clicking thumbnails. Core features: open/close animation, ESC to close, click-to-dismiss, left/right navigation, touch swipe support.
The Code
function openLightbox(img) {
currentImages = Array.from(document.querySelectorAll('.gallery img'));
currentIndex = currentImages.indexOf(img);
updateLightboxImage();
document.getElementById('lightbox').classList.add('active');
document.body.style.overflow = 'hidden';
}
document.addEventListener('keydown', (e) => {
if (!lb.classList.contains('active')) return;
if (e.key === 'Escape') closeLightbox();
if (e.key === 'ArrowLeft') navigateLightbox(-1);
if (e.key === 'ArrowRight') navigateLightbox(1);
});
Progressive Loading
Show thumbnail first, then swap to full-res once loaded — users never see a blank screen.
Why Not a Plugin
- Lightbox2: 50KB + jQuery dependency
- Fancybox: 80KB, complex config
- Vanilla JS: <2KB, zero deps, total freedom
本文是 Web Component Dictionary 组件介绍系列第18篇。查看全部83个组件:在线体验