Gallery Lightbox Stage
介绍
深色画框按作品原始比例展示大图,切换时画面轻微缩放淡入、文字上浮;底部悬浮控制条含上一张、页码、下一张和自动播放,播放时显示进度细线,支持方向键切换。
拆自整页模板 砚白 独立设计师作品集,可以单独使用,也能和同一模板拆出的其他组件拼回整页。
纯 HTML、CSS 与少量原生 JS,没有框架依赖。复制提示词交给 Claude Code、Cursor、Trae 或 Codex,模型会把 Gallery Lightbox Stage 加进你的项目并换成你的配色。
适用场景
图片对比、视频展示、画廊、轮播和媒体卡片。
安装
订阅 Builder 后,用 8pt CLI 装进项目,或在已接入 8pt MCP 的编辑器里直接调用。
$ npm i -g @8pt-dev/cli && 8pt add gallery-lightbox-stage
mcp › 使用 8pt MCP 调用 get_component("gallery-lightbox-stage")
代码
Gallery Lightbox Stage 的源码,动效只用 transform 与 opacity,并尊重减少动态效果设置。
<div class="x-gls"><div class="x-gls__stage" tabindex="0" aria-label="作品大图"><span class="tin"></span><span class="x-gls__prog"></span></div><div class="x-gls__bar"><button type="button" class="x-gls__btn" data-step="-1" aria-label="上一张"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg></button><span class="x-gls__cnt">1 / 9</span><button type="button" class="x-gls__btn" data-step="1" aria-label="下一张"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 5.5L16 12l-6.5 6.5"/></svg></button><span class="x-gls__sep"></span><button type="button" class="x-gls__btn x-gls__pp" aria-label="自动播放" aria-pressed="false"><svg class="i-play" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 5.5v13l10.5-6.5L8 5.5z"/></svg><svg class="i-pause" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 5.5v13"/><path d="M15.5 5.5v13"/></svg></button></div></div>
.x-gls{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:22px;width:100%;max-width:1040px;margin:0 auto;color:#efe9de;font-family:"PingFang SC","Noto Sans SC","Noto Sans CJK SC",system-ui,sans-serif}.x-gls *,.x-gls *::before,.x-gls *::after{box-sizing:border-box}.x-gls svg{width:1em;height:1em;flex:none}.x-gls__stage{position:relative;width:min(100%,calc(700px * var(--ar,1.7778)));padding:6px;border-radius:22px;background:#2a2725;outline:none;box-shadow:0 0 0 1px rgba(239,233,222,.09),0 40px 120px -20px rgba(0,0,0,.9);transition:width .5s cubic-bezier(.2,.8,.2,1)}.x-gls__stage:focus-visible{box-shadow:0 0 0 2px #f0b07a,0 40px 120px -20px rgba(0,0,0,.9)}.x-gls .tin{position:relative;display:block;width:100%;aspect-ratio:var(--ar,1.7778);border-radius:17px;overflow:hidden;background:#0e0d0c;container-type:inline-size}.x-gls .tin img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;animation:x-gls-in .6s cubic-bezier(.2,.8,.2,1)}.x-gls .tin .site{z-index:2;animation:x-gls-up .7s .05s cubic-bezier(.2,.8,.2,1) both}.x-gls .d .tin::before{content:"";position:absolute;inset:0;z-index:1;background:linear-gradient(180deg,rgba(0,0,0,.28),transparent 30%,transparent 55%,rgba(0,0,0,.45))}@keyframes x-gls-in{from{opacity:0;transform:scale(1.04)}}@keyframes x-gls-up{from{opacity:0;transform:translateY(10px)}}.x-gls__prog{position:absolute;left:24px;right:24px;bottom:14px;z-index:3;height:2px;border-radius:2px;background:rgba(255,255,255,.18);transform-origin:left;transform:scaleX(0);opacity:0}.x-gls__prog.is-run{opacity:1;animation:x-gls-prog 3.2s linear forwards}@keyframes x-gls-prog{from{transform:scaleX(0);background:rgba(255,255,255,.18)}to{transform:scaleX(1);background:rgba(255,255,255,.7)}}.x-gls__bar{display:flex;align-items:center;gap:4px;height:46px;padding:0 6px;border-radius:99px;background:rgba(32,29,27,.9);box-shadow:inset 0 0 0 1px rgba(239,233,222,.09);font-size:13px;font-variant-numeric:tabular-nums}.x-gls__btn{display:grid;place-items:center;width:34px;height:34px;border:0;border-radius:50%;background:transparent;color:#efe9de;font-size:16px;cursor:pointer;transition:background .2s}.x-gls__btn:hover{background:rgba(255,255,255,.08)}.x-gls__cnt{min-width:58px;text-align:center;color:#cfc6ba}.x-gls__sep{width:1px;height:18px;margin:0 4px;background:rgba(239,233,222,.09)}.x-gls__pp .i-pause{display:none}.x-gls__pp[aria-pressed="true"] .i-pause{display:block}.x-gls__pp[aria-pressed="true"] .i-play{display:none}@media (prefers-reduced-motion:reduce){.x-gls .tin img,.x-gls .tin .site,.x-gls__prog.is-run{animation:none}.x-gls__stage{transition:none}}.x-gls .site{position:absolute;inset:0;padding:5.2cqw 5.6cqw;display:flex;flex-direction:column;color:#fff;font-size:1.7cqw;line-height:1.4;text-align:left;pointer-events:none}.x-gls .lt .site{color:#1f1b17}.x-gls .s-top{display:flex;justify-content:space-between;align-items:flex-start;gap:3cqw;font-size:1.8cqw}.x-gls .s-logo{font-weight:700;letter-spacing:.06em}.x-gls .s-nav{display:flex;gap:2.8cqw;opacity:.78}.x-gls .s-nav i,.x-gls .s-cols i,.x-gls .s-foot i{font-style:normal}.x-gls .s-h{margin-top:auto;font-size:5.6cqw;line-height:1.14;font-weight:650;letter-spacing:.01em;text-shadow:0 .4cqw 2cqw rgba(0,0,0,.25)}.x-gls .lt .s-h{text-shadow:none}.x-gls .s-h2{font-size:3.4cqw;line-height:1.18;font-weight:650}.x-gls .s-cols{display:grid;grid-template-columns:repeat(3,auto);gap:.8cqw 4cqw;font-size:1.6cqw;opacity:.8}.x-gls .s-p{margin-top:1.4cqw;font-size:1.75cqw;opacity:.72;max-width:52%}.x-gls .s-btn{align-self:flex-start;margin-top:2.4cqw;padding:1.1cqw 2.5cqw;border-radius:99px;background:rgba(255,255,255,.94);color:#151311;font-size:1.65cqw;font-weight:600}.x-gls .s-dk{background:#1f1b17;color:#f4efe6}.x-gls .s-r{align-self:flex-end;text-align:right}.x-gls .s-c{align-self:center;text-align:center;max-width:none}.x-gls .s-cb{align-self:center}.x-gls .s-up{margin-top:6cqw;margin-bottom:auto}.x-gls .s-big{margin-top:auto;align-self:center;font-size:21cqw;font-weight:800;line-height:.9;color:#fff;letter-spacing:.04em;text-shadow:0 1cqw 4cqw rgba(30,60,20,.25)}.x-gls .s-foot{display:flex;justify-content:space-between;margin-top:2cqw;font-size:1.5cqw;opacity:.75;color:#fff}.x-gls .s-404{margin:auto auto 0;font-size:17cqw;font-weight:800;line-height:1;letter-spacing:.04em;color:rgba(255,255,255,.9);text-shadow:0 0 6cqw rgba(120,220,255,.35)}.x-gls .s-link{margin-top:2.4cqw;font-size:1.7cqw;opacity:.85}.x-gls .s-pill{padding:.8cqw 2cqw;border:1px solid rgba(255,255,255,.35);border-radius:99px;font-size:1.5cqw}.x-gls .s-hint{align-self:flex-end;margin-top:-2cqw;font-size:1.4cqw;opacity:.55}(root) => {
const C = [{"k": "lantern", "ar": 1.7778, "t": "d", "name": "灯屿 · 夜读", "img": "https://8pt.dev/api/media/596ca18adba2d1c8eb2b5f28.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">灯屿</b><span class=\"s-nav\"><i>夜读</i><i>札记</i><i>关于</i></span></span><span class=\"s-h\">把夜晚<br>留给慢下来的人</span><span class=\"s-p\">收藏值得读的文字,等夜深时再慢慢翻开</span><span class=\"s-btn\">进入夜读</span>"}, {"k": "bamboo", "ar": 1.7778, "t": "l", "name": "竹息 · 林间", "img": "https://8pt.dev/api/media/2a48eefd24317a44b0258c79.webp", "site": "<span class=\"s-top\"><span class=\"s-h2\">一处安静的<br>林间角落</span><span class=\"s-cols\"><i>白噪音</i><i>专注</i><i>日志</i><i>花园</i><i>关于</i><i>联系</i></span></span><span class=\"s-big\">竹息</span><span class=\"s-foot\"><i>© 竹息</i><i>隐私 · 条款</i></span>"}, {"k": "door", "ar": 1.7778, "t": "d", "name": "沙门 · 出口", "img": "https://8pt.dev/api/media/1a24aa1e7d9544d8f8a6da70.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">沙门</b><span class=\"s-nav\"><i>故事</i><i>出口</i></span></span><span class=\"s-h\">走出<br>信息流</span><span class=\"s-p\">推开门,世界会安静一点</span><span class=\"s-link\">点击进入 →</span>"}, {"k": "telescope", "ar": 1.3333, "t": "l", "name": "云镜 · 观测", "img": "https://8pt.dev/api/media/ec31ce9b0b61db0d2b2d1f92.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">云镜</b><span class=\"s-nav\"><i>观测</i><i>星图</i><i>订阅</i></span></span><span class=\"s-h s-r\">看得更远<br>一点点</span><span class=\"s-p s-r\">把日落之后的天空装进口袋</span>"}, {"k": "sunken", "ar": 1.7778, "t": "d", "name": "沉舟 · 404", "img": "https://8pt.dev/api/media/2a2e69f3d62322e9318bb4c6.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">沉舟</b><span class=\"s-nav\"><i>返回</i></span></span><span class=\"s-404\">404</span><span class=\"s-p s-c\">这一页沉到海底了</span><span class=\"s-btn s-cb\">浮回首页</span>"}, {"k": "globe", "ar": 1.3333, "t": "l", "name": "雪屋 · 冬日", "img": "https://8pt.dev/api/media/18decab4de8eda12bcd7ab66.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">雪屋</b><span class=\"s-nav\"><i>小屋</i><i>手作</i><i>候补</i></span></span><span class=\"s-h\">冬天的<br>小屋</span><span class=\"s-btn s-dk\">加入候补</span>"}, {"k": "clay", "ar": 0.75, "t": "l", "name": "陶序 · 器物", "img": "https://8pt.dev/api/media/b72329bcdf3f85eb9382a8ad.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">陶序</b><span class=\"s-nav\"><i>器物</i><i>工坊</i></span></span><span class=\"s-h\">器物<br>与留白</span><span class=\"s-p\">手捏的形状,安静的颜色</span>"}, {"k": "book", "ar": 1.7778, "t": "d", "name": "星页 · 阅读", "img": "https://8pt.dev/api/media/6e610c02b7c385e2fd9b5975.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">星页</b><span class=\"s-nav\"><i>书架</i><i>星图</i><i>我的</i></span></span><span class=\"s-h s-c s-up\">每一页<br>都是一片星空</span><span class=\"s-btn s-cb\">开始阅读</span>"}, {"k": "glass", "ar": 1.7778, "t": "d", "name": "棱光 · 发布", "img": "https://8pt.dev/api/media/44f2c620b7b4377af63ad5b3.webp", "site": "<span class=\"s-top\"><b class=\"s-logo\">棱光</b><span class=\"s-pill\">预约体验</span></span><span class=\"s-h\">一束光,<br>万种颜色</span><span class=\"s-p\">透过一块玻璃,看见光的全部</span><span class=\"s-hint\">向下浏览</span>"}];
const N = C.length;
const stage = root.querySelector('.x-gls__stage');
const tin = stage.querySelector('.tin');
const prog = root.querySelector('.x-gls__prog');
const cnt = root.querySelector('.x-gls__cnt');
const pp = root.querySelector('.x-gls__pp');
let cur = 0, timer = 0;
const mod = (a, b) => ((a % b) + b) % b;
function show(i) {
cur = mod(i, N);
…订阅 Builder 查看完整源码。查看价格