一个基于 Swiper.js 实现的双层响应式视觉组件:首层在沉浸式背景中展示横向概念卡片,点击卡片右下角按钮后,进入全屏 Modal Gallery,并通过第二个 Swiper 浏览对应的详情图片与说明。
项目重点不是复杂动画,而是将 内容浏览 → 查看详情 → 沉浸式图片浏览 三个阶段自然串联起来,同时保持 HTML、CSS、JavaScript 结构简单,便于直接拆分、修改和复用到企业官网、产品站、作品集与项目案例页面中。
页面由背景、介绍文字与横向卡片轮播共同组成一个完整 Section。
- 桌面端:左侧介绍文字,右侧横向主卡片
- 主轮播使用
slidesPerView: 'auto' - 当前视口可同时看到约两张完整卡片,并保留下一张局部预览
- 使用数字分页
01 / 02 / 03 / 04 - 卡片右下角提供详情入口
- 支持鼠标拖动与触控滑动
点击主卡片后打开公共全屏 Gallery。
- 中间图片作为当前焦点
- 左右图片保留局部预览
- 非活动图片使用深色遮罩降低视觉权重
- 当前标题和说明同步高亮
- 支持左右箭头、键盘方向键和触控滑动
- 支持关闭按钮、点击背景关闭和
Esc关闭 - Modal 打开时锁定页面滚动
这个项目包含两个职责明确的 Swiper,而不是把所有内容塞进一个复杂轮播中。
Main Swiper
│
├── 主卡片 01
├── 主卡片 02
├── 主卡片 03
└── 主卡片 04
│
│ 点击详情按钮
↓
Shared Modal
│
↓
Gallery Swiper
├── Detail 01
├── Detail 02
├── Detail 03
├── Detail 04
└── Detail 05
每张主卡片并没有对应一套独立 Modal HTML,而是通过 data-gallery 指定数据分组,再由 JavaScript 将对应 Gallery 内容写入同一个公共 Modal。
这种方式相比“4 张卡片 + 4 套 Modal”更适合长期维护:
- DOM 更轻
- Modal 结构只维护一份
- 关闭、键盘、滚动锁定等逻辑不需要重复
- 后续增加产品或案例时,只需要增加卡片与对应数据
- 更适合从静态 Demo 迁移到真实项目
- HTML5
- CSS3
- 原生 JavaScript
- Swiper.js
slidesPerView: 'auto'centeredSlides: true- CSS
aspect-ratio - CSS Overlay / Gradient
backdrop-filter- 响应式固定宽度卡片
- 公共 Modal 数据切换
- Body Scroll Lock
- Keyboard Navigation
prefers-reduced-motion
项目不使用:
- npm
- 构建工具
- React / Vue
- jQuery
- 在线 CDN
- 额外 Gallery 插件
Swiper 的 CSS 与 JavaScript 均保存在本地目录中,可以直接离线运行。
overlay-card-modal-gallery/
├── index.html
├── README.md
│
├── css/
│ └── style.css
│
├── js/
│ └── main.js
│
├── images/
│ ├── background.svg
│ ├── cards/
│ │ ├── 01.svg
│ │ ├── 02.svg
│ │ ├── 03.svg
│ │ └── 04.svg
│ │
│ └── gallery/
│ ├── 01-01.svg
│ ├── 01-02.svg
│ ├── ...
│ └── 04-05.svg
│
└── vendor/
└── swiper/
├── swiper-bundle.min.css
└── swiper-bundle.min.js
| 文件 | 作用 |
|---|---|
index.html |
页面结构、主卡片和公共 Modal |
css/style.css |
全部视觉样式与响应式规则 |
js/main.js |
Main Swiper、Gallery 数据、Modal 与 Gallery Swiper |
images/background.svg |
Section 背景占位图 |
images/cards/ |
首层主卡片图片 |
images/gallery/ |
Modal Gallery 详情图片 |
vendor/swiper/ |
本地 Swiper 资源 |
本项目没有把桌面布局简单等比例缩小,而是针对手机端重新组织内容层级。
桌面端采用:
介绍文字 + 主卡片轮播
主卡片通过百分比宽度与 slidesPerView: 'auto' 配合,让视口自然决定实际可见数量。
设计重点是:
[ Card 01 ] [ Card 02 ] [ 下一张局部预览 ]
这种 Partial Visibility 本身就是一种导航提示,用户不需要额外说明,也能理解内容可以继续横向浏览。
在 1023px 以下切换为:
介绍文字
↓
横向卡片轮播
主卡片尺寸固定为:
259 × 380px
卡片保持固定自然尺寸,而不是使用 width: 100%。因此手机视口中会明显露出下一张卡片,强化横向滑动提示。
这一策略与普通“手机一屏一张”轮播不同,它更适合视觉型产品、案例和作品展示。
主轮播使用:
new Swiper('.feature-swiper', {
slidesPerView: 'auto',
spaceBetween: 20,
speed: 700,
grabCursor: true
});如果直接使用:
slidesPerView: 2Swiper 会按照当前容器宽度平均计算卡片尺寸。
本项目更关注每张卡片本身的自然比例,因此由 CSS 控制 Slide 宽度,再让 Swiper 使用:
slidesPerView: 'auto'这样桌面和手机都可以分别定义最舒服的卡片尺寸。
默认 Swiper Pagination 通常显示:
● ● ● ●
本项目通过 renderBullet() 将其改为:
01 02 03 04
示例:
renderBullet(index, className) {
return `<button class="${className}">${String(index + 1).padStart(2, '0')}</button>`;
}这种数字分页更适合设计感较强的产品、汽车、建筑和作品集页面。
Gallery 内容集中维护在 js/main.js:
const galleryData = {
desert: [
['01-01.svg', '标题', '说明'],
['01-02.svg', '标题', '说明']
],
expedition: [
// ...
]
};主卡片通过:
<button data-gallery="desert">与对应数据建立关系。
因此增加新系列时,主要修改两个地方:
index.html增加一张主卡片main.js增加对应 Gallery 数据
不需要复制新的 Modal 结构。
Modal 中的第二个 Swiper 使用:
new Swiper('.gallery-swiper', {
slidesPerView: 'auto',
centeredSlides: true,
spaceBetween: 20
});核心参数:
centeredSlides: true让当前图片始终位于视觉中心,同时在两侧保留 Previous / Next Slide。
项目没有使用 Coverflow、Cards 或复杂 3D Effect。
视觉焦点主要由 CSS 完成:
Previous Active Next
暗 亮 暗
非活动图片覆盖深色遮罩:
.gallery-media::after {
background: rgba(0, 0, 0, 0.8);
}活动图片取消遮罩:
.swiper-slide-active .gallery-media::after {
opacity: 0;
}这比复杂 3D 动画更克制,也更适合企业网站和高端视觉项目。
手机端没有继续照搬桌面 Gallery,而是切换为更适合阅读的卡片结构:
┌─────────────────────┐
│ │
│ IMAGE │
│ │
├─────────────────────┤
│ 标题 │
│ │
│ 描述文字 │
│ │
└─────────────────────┘
主要变化:
- 当前卡片放大到正常比例
- 前后卡片轻微缩小
- 图片下方增加白色说明区域
- 隐藏桌面左右箭头
- 主要使用手势滑动
- 显示当前页 / 总页数
这体现了一个重要原则:
响应式设计不等于把桌面页面缩小,而是根据设备重新选择最合适的信息组织方式。
当前支持:
- 点击卡片详情按钮打开 Gallery
- 点击右上角关闭按钮关闭
- 点击背景关闭
Esc关闭- 键盘
← / →切换图片 - 鼠标拖动
- 手机触控滑动
- Modal 打开时禁止背景页面滚动
- Modal 关闭后将焦点返回原按钮
打开 Gallery 时,Swiper 在 Modal 显示后再初始化,避免隐藏容器初始化时出现宽度计算错误。
将:
images/cards/01.svg
替换成真实图片,并同步修改:
<img src="images/cards/01.jpg" alt="产品名称">将真实详情图放入:
images/gallery/
然后修改 main.js:
['product-01.jpg', '产品细节', '对应说明文字']可以直接替换:
images/background.svg
也可以在 style.css 中修改背景路径。
这个组件尤其适合需要“先快速浏览,再深入查看”的内容。
产品系列卡片
↓
点击详情
↓
产品结构 / 纹理 / 尺寸 / 场景 Gallery
酒店 / 公寓 / 办公 / 商业项目
↓
项目详情 Gallery
↓
空间图 / 材料细节 / 施工节点 / 完成效果
- 汽车车型
- 家具产品
- 建筑材料
- 室内设计
- 工业设计
- 作品集
- 区域解决方案
- 品牌概念项目
- 高端产品展示
两个 Swiper 的职责完全不同:
Main Swiper
= 内容发现
Gallery Swiper
= 内容深入浏览
不要为了减少代码而把它们合并成一个复杂 Swiper。
如果后续增加到 10~20 个产品,独立 Modal 会快速增加 HTML 体积与维护成本。
继续使用:
多张主卡
+
一个公共 Modal
+
数据驱动 Gallery
更适合长期维护。
当前 Gallery 的核心是:
位置 + 明暗 + 焦点
已经足够形成明显层次。
除非真实项目有明确需求,否则不建议额外加入:
- 3D Coverflow
- 自动播放
- 大幅缩放
- 大角度旋转
- 多层时间轴动画
避免为了增加功能而破坏内容浏览体验。
项目包含基础可访问性处理:
- 按钮使用明确的
aria-label - Modal 使用
aria-modal="true" - 打开和关闭时更新
aria-hidden - 支持键盘关闭与方向键浏览
- Modal 关闭后恢复触发按钮焦点
- 支持
prefers-reduced-motion
如果用于正式生产环境,还可以继续增加更完整的 Focus Trap。
建议使用现代浏览器查看:
- Chrome
- Edge
- Firefox
- Safari
项目使用了 aspect-ratio、backdrop-filter 等现代 CSS 特性,不以老旧浏览器兼容为主要目标。
在不改变当前架构的前提下,可以继续扩展:
- Gallery 图片改为真实项目照片
- Gallery 支持视频 Slide
- 主卡片增加分类筛选
- Gallery 数据改为独立 JSON
- 与 WordPress 自定义文章类型连接
- 从产品 Meta 字段生成 Gallery 数据
- 增加图片懒加载
- 增加更完整的 Focus Trap
如果用于普通静态展示,当前版本已经足够,不建议为了扩展而提前增加额外依赖。
首个稳定版本:
- 完成沉浸式 Overlay Card Carousel
- 完成桌面与手机响应式布局
- 完成数字 Pagination
- 完成单一公共 Modal 架构
- 完成 Centered Gallery Swiper
- 完成活动图片焦点效果
- 完成桌面左右预览与手机卡片式 Gallery
- 完成键盘、背景关闭与 Body Scroll Lock
- Swiper CSS / JS 全部本地化
本项目主要用于前端布局、Swiper 交互与响应式设计学习,可根据自己的实际项目需要继续修改和扩展。