8pt

Infinite Drag Wall

无限拖拽作品墙•媒体
介绍

错落排布的作品卡片铺成无边画布,按住即可向任意方向拖动并带惯性滑行,滚轮也能平移;卡片按距离依次淡入,点击放大查看并可左右切换。适合作品集首页与灵感墙。

拆自整页模板 砚白 独立设计师作品集,可以单独使用,也能和同一模板拆出的其他组件拼回整页。

纯 HTML、CSS 与少量原生 JS,没有框架依赖。复制提示词交给 Claude Code、Cursor、Trae 或 Codex,模型会把 Infinite Drag Wall 加进你的项目并换成你的配色。

适用场景

图片对比、视频展示、画廊、轮播和媒体卡片。

安装

订阅 Builder 后,用 8pt CLI 装进项目,或在已接入 8pt MCP 的编辑器里直接调用。

$ npm i -g @8pt-dev/cli && 8pt add infinite-drag-wall
mcp › 使用 8pt MCP 调用 get_component("infinite-drag-wall")

代码

Infinite Drag Wall 的源码,动效只用 transform 与 opacity,并尊重减少动态效果设置。

<div class="x-idw"><div class="x-idw__wall" aria-label="作品画布"><div class="x-idw__world"></div></div><div class="x-idw__view" role="dialog" aria-label="作品大图"><div class="x-idw__stage"><button type="button" class="x-idw__btn x-idw__x" aria-label="关闭"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11"/><path d="M17.5 6.5l-11 11"/></svg></button><span class="tin"></span></div><div class="x-idw__bar"><button type="button" class="x-idw__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-idw__cnt">1 / 9</span><button type="button" class="x-idw__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></div></div></div>
.x-idw{box-sizing:border-box;position:relative;width:100%;max-width:1200px;height:820px;margin:0 auto;border-radius:24px;overflow:hidden;background:radial-gradient(120% 90% at 60% 40%,#1b1816 0%,#100e0d 70%);font-family:"PingFang SC","Noto Sans SC","Noto Sans CJK SC",system-ui,sans-serif;color:#efe9de;box-sizing:border-box}.x-idw *,.x-idw *::before,.x-idw *::after{box-sizing:border-box}.x-idw__wall{position:absolute;inset:0;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}.x-idw__wall.is-drag{cursor:grabbing}.x-idw__world{position:absolute;left:0;top:0;will-change:transform}.x-idw .tile{position:absolute;padding:5px;border:0;border-radius:19px;background:#2a2725;cursor:inherit;box-shadow:0 0 0 1px rgba(255,255,255,.04),0 18px 40px -18px rgba(0,0,0,.7);opacity:0;transform:scale(.94);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1),background .3s}.x-idw .tile.in{opacity:1;transform:none}.x-idw .tile:hover{background:#34302d}.x-idw .tile:focus-visible{outline:2px solid #f0b07a;outline-offset:2px}.x-idw .tin{position:relative;display:block;width:100%;height:100%;border-radius:14px;overflow:hidden;background:#0e0d0c;container-type:inline-size}.x-idw .tin img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;-webkit-user-drag:none;transition:transform 1.2s cubic-bezier(.2,.7,.2,1)}.x-idw .tile:hover .tin img{transform:scale(1.035)}.x-idw .tin::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px rgba(255,255,255,.06);pointer-events:none}.x-idw .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))}.x-idw .site{z-index:2}.x-idw__view{position:absolute;inset:0;z-index:5;display:grid;place-items:center;padding:40px 40px 96px;background:rgba(10,9,8,.6);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);opacity:0;visibility:hidden;transition:opacity .35s,visibility .35s}.x-idw__view.is-open{opacity:1;visibility:visible}.x-idw__stage{position:relative;width:min(100%,calc(640px * var(--ar,1.7778)));padding:6px;border-radius:22px;background:#2a2725;box-shadow:0 0 0 1px rgba(239,233,222,.09),0 40px 120px -20px rgba(0,0,0,.9);transform:translateY(14px) scale(.98);transition:transform .45s cubic-bezier(.2,.8,.2,1)}.x-idw__view.is-open .x-idw__stage{transform:none}.x-idw__stage .tin{height:auto;aspect-ratio:var(--ar,1.7778);border-radius:17px}.x-idw__btn{display:grid;place-items:center;width:36px;height:36px;border:0;border-radius:50%;background:#2c2927;color:#efe9de;box-shadow:inset 0 0 0 1px rgba(239,233,222,.09);font-size:16px;cursor:pointer;transition:background .2s}.x-idw__btn:hover{background:#38332f}.x-idw__btn svg{width:1em;height:1em}.x-idw__x{position:absolute;top:-14px;right:-14px;z-index:3}.x-idw__bar{position:absolute;left:50%;bottom:28px;display:flex;align-items:center;gap:6px;height:46px;padding:0 6px;border-radius:99px;background:rgba(32,29,27,.88);box-shadow:inset 0 0 0 1px rgba(239,233,222,.09);transform:translateX(-50%);font-size:13px;font-variant-numeric:tabular-nums}.x-idw__bar .x-idw__btn{width:34px;height:34px;background:transparent;box-shadow:none}.x-idw__bar .x-idw__btn:hover{background:rgba(255,255,255,.08)}.x-idw__cnt{min-width:54px;text-align:center;color:#cfc6ba}@media (max-width:640px){.x-idw{height:620px}.x-idw__view{padding:20px 16px 90px}}@media (prefers-reduced-motion:reduce){.x-idw .tile,.x-idw .tin img,.x-idw__view,.x-idw__stage{transition:none}.x-idw .tile{opacity:1;transform:none}}.x-idw .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-idw .lt .site{color:#1f1b17}.x-idw .s-top{display:flex;justify-content:space-between;align-items:flex-start;gap:3cqw;font-size:1.8cqw}.x-idw .s-logo{font-weight:700;letter-spacing:.06em}.x-idw .s-nav{display:flex;gap:2.8cqw;opacity:.78}.x-idw .s-nav i,.x-idw .s-cols i,.x-idw .s-foot i{font-style:normal}.x-idw .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-idw .lt .s-h{text-shadow:none}.x-idw .s-h2{font-size:3.4cqw;line-height:1.18;font-weight:650}.x-idw .s-cols{display:grid;grid-template-columns:repeat(3,auto);gap:.8cqw 4cqw;font-size:1.6cqw;opacity:.8}.x-idw .s-p{margin-top:1.4cqw;font-size:1.75cqw;opacity:.72;max-width:52%}.x-idw .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-idw .s-dk{background:#1f1b17;color:#f4efe6}.x-idw .s-r{align-self:flex-end;text-align:right}.x-idw .s-c{align-self:center;text-align:center;max-width:none}.x-idw .s-cb{align-self:center}.x-idw .s-up{margin-top:6cqw;margin-bottom:auto}.x-idw .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-idw .s-foot{display:flex;justify-content:space-between;margin-top:2cqw;font-size:1.5cqw;opacity:.75;color:#fff}.x-idw .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-idw .s-link{margin-top:2.4cqw;font-size:1.7cqw;opacity:.85}.x-idw .s-pill{padding:.8cqw 2cqw;border:1px solid rgba(255,255,255,.35);border-radius:99px;font-size:1.5cqw}.x-idw .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 wall = root.querySelector('.x-idw__wall');
  const world = root.querySelector('.x-idw__world');
  const view = root.querySelector('.x-idw__view');
  const stage = root.querySelector('.x-idw__stage');
  const vtin = stage.querySelector('.tin');
  const cnt = root.querySelector('.x-idw__cnt');
  const mod = (a, b) => ((a % b) + b) % b;
  const timers = new Set();
  let TW, G, H, P, cam = { x: 0, y: 0 }, vel = { x: 0, y: 0 }, raf = 0, drag = null, moved = 0, cur = 0, t0 = performance.now();
…
订阅 Builder 查看完整源码。查看价格

同一模板的其他组件

查看全部

Gallery Lightbox Stage

Project Brief Form

Glow Pill Buttons

Electric Border Pricing

Portfolio Intro Hero

Local Time Status

更多媒体组件

查看全部

Crossfade Media Stage

Tinted Team Cards

Kanban Window Mock

Hover Reveal Work Grid

Template Card Grid

Paywall Flow Strip

Gallery Lightbox Stage

Library Browser Mock

更多组件

查看全部

Tabbed Logo Testimonial

Dot Matrix Glow Hero

Dotted Globe Features

Chaos Versus Ship Split

Segmented Pricing Tiers

Live Deploy Bento

Floating Tile CTA Banner

Aurora Prompt Hero

继续探索