Lightbox (燈箱):以半透明遮罩層覆蓋頁面其餘區域,中央顯示聚焦內容 (圖片、表單、訊息),強制使用者在關閉前完成互動。視覺效果類似 Windows 登出/關機對話框。
showModalDialog()、早期「Inline Popup」繞過彈窗攔截器。| 階段 | 代表 | 關鍵技術 | 特點 |
|---|---|---|---|
| 1. 原生 Lightbox (2006) | Lokesh Dhakar | CSS 定位 + 半透明 PNG 背景 + Prototype.js | 專注圖片放大、標記 rel="lightbox"、無依賴輕量 |
| 2. Lightbox Gone Wild | Chris Campbell | Prototype 1.4 + CSS class 驅動 + Ajax.Updater | 擴展為通用 Modal 容器、支援表單動態載入、但有 CPU 100% Bug |
| 3. alwaysBETA 改良版 | alwaysBETA | Moo.fx 動畫庫 + 精簡核心 | 效能優化、易定制、動畫流暢 |
| 4. 現代生態 | Bootstrap Modal, Ant Design Modal, Headless UI, Radix UI | React/Vue/Svelte 組件化、Portal 渲染、Focus Trap、ARIA 無障礙、動畫過渡 | 框架深度整合、TypeScript、測試完備、無障礙合規 |
// HTML 結構
// CSS 關鍵
.lightbox-overlay {
position: fixed; inset: 0; background: rgba(0,0,0,0.6);
display: flex; align-items: center; justify-content: center;
z-index: 1000; opacity: 0; transition: opacity 0.2s;
pointer-events: none;
}
.lightbox-overlay:not([hidden]) { opacity: 1; pointer-events: auto; }
.lightbox-content { background: white; padding: 1.5rem; border-radius: 8px; max-width: 90vw; max-height: 90vh; overflow: auto; transform: scale(0.9); transition: transform 0.2s; }
.lightbox-overlay:not([hidden]) .lightbox-content { transform: scale(1); }
// JS 控制器
class Lightbox {
constructor() {
this.overlay = document.getElementById('overlay');
this.title = this.overlay.querySelector('#lb-title');
this.body = this.overlay.querySelector('.lightbox-body');
this.closeBtn = this.overlay.querySelector('.lightbox-close');
this._prevFocus = null;
this._bindEvents();
}
_bindEvents() {
this.closeBtn.onclick = () => this.hide();
this.overlay.onclick = e => { if (e.target === this.overlay) this.hide(); };
document.addEventListener('keydown', e => { if (e.key === 'Escape') this.hide(); });
}
show(title, html) {
this._prevFocus = document.activeElement;
this.title.textContent = title;
this.body.innerHTML = html;
this.overlay.hidden = false;
document.body.style.overflow = 'hidden'; // 防止背景滾動
this.closeBtn.focus(); // 焦點陷阱起點
this._trapFocus();
}
hide() {
this.overlay.hidden = true;
document.body.style.overflow = '';
this._prevFocus?.focus(); // 歸還焦點
}
_trapFocus() {
const focusable = this.overlay.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
const first = focusable[0], last = focusable[focusable.length - 1];
this.overlay.addEventListener('keydown', e => {
if (e.key !== 'Tab') return;
if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
});
}
}
// 使用
const lb = new Lightbox();
document.getElementById('open-btn').onclick = () => lb.show('確認刪除', '確定要刪除此項目嗎?
');
role="dialog" + aria-modal="true"。aria-labelledby 指向標題。aria-hidden="true" 或 inert 屬性 (現代瀏覽器支援)。| 模式 | 用途 | 關鍵差異 |
|---|---|---|
| Drawer / Side Panel | 手機端表單、導航、購物車 | 從邊緣滑入、不完全遮罩、可拖拽關閉 |
| Toast / Snackbar | 非阻塞通知 | 自動消失、不模態、底部/頂部浮現 |
| Fullscreen Takeover | 複雜精靈、編輯器 | 佔滿視口、類似頁面跳轉但保留上下文 |
| Nested Modal | 確認對話框在表單 Modal 之上 | 堆疊 z-index、焦點管理更複雜 |
IntersectionObserver 或點擊時才 fetch 載入。transform: scale/translate + opacity 觸發 GPU 加速。Lightbox 從「破解彈窗攔截的 Hack」進化為現代 Web 應用不可或缺的模態互動基石。核心價值在於視覺層級管理與強制任務完成。現代實作應以組件化、無障礙、動畫流暢、焦點安全為標準,優先採用成熟 UI 庫 (Radix UI, Headless UI, Bootstrap 5 Modal) 而非手寫,將精力投入業務邏輯與用戶體驗細節打磨。