使用纯 CSS 构建流畅的轮播图

多年以来,创建轮播图意味着需要使用 JavaScript 库,如 Swiper 或 Glide。每个库都会为你的打包文件增加数千字节,引入依赖项,并需要仔细管理事件监听器和状态。但现代 CSS 已经悄然演进,能够原生处理轮播图——无需 JavaScript。
本文探讨如何使用 scroll-snap、实验性伪元素以及其他纯 CSS 技术构建高性能、可访问的 CSS 轮播图,这些技术不仅现在可用,而且在未来数年内仍将保持相关性。
核心要点
- Scroll-snap 属性可将任何可滚动容器转换为流畅的轮播体验
- Chrome 135+ 中的实验性伪元素支持无需 JavaScript 的原生导航控件
- 纯 CSS 轮播图通过消除 JavaScript 解析和事件监听器来提升性能
- 降级策略确保兼容性,同时为未来的浏览器特性做好准备
基础:Scroll Snap CSS
任何纯 CSS 轮播图的基石都是 scroll-snap 属性。它只需几行代码就能将可滚动容器转换为分页体验:
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
}
.carousel-item {
flex: 0 0 100%;
scroll-snap-align: center;
}
这将创建一个水平轮播图,其中每个项目都会对齐到位。mandatory
关键字确保用户始终停留在完整的幻灯片上,而 scroll-behavior: smooth
则在项目之间添加流畅的过渡效果。
Scroll Snap CSS 在所有现代浏览器中都能工作,使其成为无 JavaScript 轮播图最可靠的基础。对于响应式设计,可以将其与 CSS Grid 结合使用,或调整 flex-basis 以在每个视图中显示多个项目:
.carousel-item {
flex: 0 0 calc(33.333% - 1rem);
margin: 0 0.5rem;
}
现代导航:实验性伪元素
Chrome 135+ 引入了可自动生成轮播控件的实验性伪元素。这些特性需要在 Chrome 标志中启用实验性 Web 平台功能。
::scroll-button
伪元素无需额外标记即可创建上一个/下一个按钮:
.carousel::scroll-button(inline-start),
.carousel::scroll-button(inline-end) {
background: rgba(0, 0, 0, 0.5);
color: white;
padding: 1rem;
border: none;
}
.carousel::scroll-button(inline-start)::before {
content: "←";
}
.carousel::scroll-button(inline-end)::before {
content: "→";
}
类似地,::scroll-marker
为每个可滚动部分生成分页指示点:
.carousel {
scroll-marker-group: after;
}
.carousel-item::scroll-marker {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background: #ccc;
}
.carousel-item::scroll-marker:target-current {
background: #333;
}
请注意,这些伪元素是实验性的,其语法可能会发生变化。:target-current
伪类会在用户滚动时高亮显示活动标记。这些特性减少了 JavaScript 需求,同时提供原生的可访问性支持。
Discover how at OpenReplay.com.
生产环境的降级策略
由于 scroll-button 和 scroll-marker 的浏览器支持有限,请使用 @supports
进行特性检测:
/* 降级导航 */
.carousel-nav {
display: flex;
gap: 0.5rem;
}
/* 当支持原生控件时隐藏降级方案 */
@supports (scroll-button-inline: both) {
.carousel-nav {
display: none;
}
}
为了更广泛的兼容性,可以将 scroll-snap 与锚点链接结合用于导航:
<nav class="carousel-nav">
<a href="#slide1">1</a>
<a href="#slide2">2</a>
<a href="#slide3">3</a>
</nav>
<div class="carousel">
<div id="slide1" class="carousel-item">...</div>
<div id="slide2" class="carousel-item">...</div>
<div id="slide3" class="carousel-item">...</div>
</div>
无需 JavaScript 的 CSS 自动播放轮播图
创建 CSS 自动播放轮播图只需要关键帧动画:
@keyframes slide {
0%, 20% { transform: translateX(0); }
25%, 45% { transform: translateX(-100%); }
50%, 70% { transform: translateX(-200%); }
75%, 95% { transform: translateX(-300%); }
100% { transform: translateX(0); }
}
.autoplay-carousel {
display: flex;
animation: slide 12s infinite;
}
.autoplay-carousel:hover {
animation-play-state: paused;
}
这种技术工作可靠,但以简单性换取了用户控制。悬停时暂停可提高可用性,结合 prefers-reduced-motion
可以尊重可访问性偏好:
@media (prefers-reduced-motion: reduce) {
.autoplay-carousel {
animation: none;
}
}
可访问性与性能
纯 CSS 轮播图在性能方面表现出色——无需 JavaScript 解析、无事件监听器、无布局抖动。浏览器的原生滚动自动处理触摸、键盘和鼠标输入。
为了确保可访问性:
- Scroll-snap 提供流畅的滚动,但完整的键盘导航和可访问控件需要新的 ::scroll-button 和 ::scroll-marker 特性
- 焦点指示器保持可见
- 当 CSS 失效时内容仍然可访问
- 触摸目标满足 44×44px 的最小尺寸
添加 ARIA 标签以改善屏幕阅读器体验:
<div class="carousel" role="region" aria-label="产品画廊">
<div class="carousel-item" aria-label="第 1 张,共 3 张">...</div>
</div>
结论
现代 CSS 在大多数情况下已经消除了对 JavaScript 轮播库的需求。Scroll-snap 提供了当前的基础,而像 scroll-button 和 scroll-marker 这样的新兴特性预示着一个复杂 UI 组件无需 JavaScript 的未来。这些技术减少了打包体积,提升了性能,并简化了维护——这些好处会随着时间的推移而累积。
从生产网站的 scroll-snap 开始。在 Chrome 中尝试新的伪元素。最重要的是,当 20 行 CSS 就能实现相同结果时,质疑你是否真的需要那个 50KB 的轮播库。
常见问题
可以,scroll-snap 属性在所有现代浏览器中都有出色的支持。实验性伪元素只应在提供适当降级方案的情况下使用,因为它们目前仅在启用标志的 Chrome 135+ 中工作。
Scroll-snap 通过原生浏览器滚动自动支持触摸手势。用户可以在幻灯片之间自然地滑动,强制对齐点确保他们始终停留在完整的幻灯片上,无需额外代码。
CSS 轮播图在 JavaScript 被禁用时仍能完美工作,因为它们完全依赖原生 CSS 属性。用户仍然可以使用触摸、鼠标或键盘进行导航,使其比基于 JavaScript 的解决方案更具弹性。
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..