当前位置:首页 > 文章列表 > 文章 > 前端 > CSS ::scroll-button 怎样给横向滚动列表添加原生箭头

CSS ::scroll-button 怎样给横向滚动列表添加原生箭头

来源:17golang原创 2026-11-07 00:30:31 0浏览 收藏
热门推荐
漫画APP
动画内容聚合,热门资源快捷查看
立即下载

如果横向卡片列表已经可以滚动,但还想给用户一个清晰的“向前/向后”入口,可以把滚动容器交给 CSS 的 ::scroll-button() 伪元素。它会在滚动容器内部生成按钮,方向由 left、right 等参数决定,不需要为箭头再写一组 JavaScript 点击逻辑。

最小做法是:让列表成为横向滚动容器,再分别给 ::scroll-button(left) 和 ::scroll-button(right) 设置非 none 的 content。按钮会随着可滚动范围自动进入可用或 disabled 状态;同时要保留原生滚动和键盘焦点作为降级入口。

官方地址:https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Overflow/Carousels

下面只讨论横向列表、前后按钮、可访问名称和状态样式,不把 ::scroll-marker 导航或 JavaScript 轮播控制混进来。

先确定 scroll container 与生成条件

::scroll-button() 的前提不是“页面上有一排卡片”,而是目标元素本身要形成滚动容器。横向列表通常需要 display:flex、不换行和 overflow-x:auto;当内容宽度超过容器时,按钮才有实际的滚动空间。

第二个关键点是生成条件:伪元素的 content 不能是 none。只写选择器而不提供内容,浏览器不会创建可交互按钮。这个判断也解释了为什么示例同时设置箭头符号和文本替代。

横向滚动容器、溢出内容、content 非 none 与左右 scroll-button 之间的静态关系说明图
图1:结构说明图,展示滚动容器与按钮生成条件的边界;这不是浏览器截图或运行证据。

分别生成 left 与 right 按钮

方向参数表达的是滚动方向,而不是按钮摆放位置。对常见的横向列表,可以把起点方向交给 left,把终点方向交给 right。按钮图标只是视觉提示,真正的滚动语义由伪元素参数决定。

.card-list {
  display: flex;
  flex-wrap: nowrap;
  gap: 1rem;
  overflow-x: auto;
  scroll-behavior: smooth;
  /* 保留原生横向滚动,兼容时仍然可以拖动或使用键盘。 */
  scrollbar-width: thin;
}

.card-list::scroll-button(left) {
  content: "‹" / "向左滚动";
}

.card-list::scroll-button(right) {
  content: "›" / "向右滚动";
}

.card-list::scroll-button(*) {
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border: 1px solid #b8c8dc;
  border-radius: 999px;
  background: #ffffff;
  color: #17324d;
  cursor: pointer;
  /* 让按钮和卡片列表之间保留明确的视觉层次。 */
  box-shadow: 0 0.25rem 0.75rem rgb(23 50 77 / 14%);
}

这里用 ::scroll-button(*) 统一设置两个按钮的外观,再用具体方向选择器提供不同图标。content 右侧的字符串是可访问名称的文本替代,避免只给辅助技术暴露一个不明确的符号。

补齐可访问性与状态样式

生成出来的按钮仍然是交互入口,不能只依赖颜色或箭头形状。键盘用户需要明确的焦点轮廓;当列表已经到达某一侧边界时,浏览器会把对应方向的按钮设置为 :disabled,此时视觉上应降低强调,并取消指针手势。

.card-list::scroll-button(*):focus-visible {
  outline: 3px solid #f0a33a;
  outline-offset: 3px;
  /* 高对比焦点轮廓不改变按钮的滚动职责。 */
}

.card-list::scroll-button(*):hover {
  background: #eef6ff;
}

.card-list::scroll-button(*):disabled {
  opacity: 0.32;
  cursor: default;
  /* 到达滚动边界后,按钮保留位置但表达不可继续滚动。 */
}

@media (prefers-reduced-motion: reduce) {
  .card-list {
    /* 用户要求减少动画时,切回即时滚动。 */
    scroll-behavior: auto;
  }
}
前后 scroll-button、可访问名称、焦点轮廓、disabled 状态与可继续滚动范围的静态依赖关系图
图2:状态说明图,展示按钮名称、焦点和 disabled 状态各自承担的职责;这不是运行截图。

:disabled 是状态反馈,不是业务代码主动维护的布尔变量。不要再用 JavaScript 监听滚动位置去重复计算同一件事;如果还需要显示页码、当前卡片或滚动标记,那是另一个交互需求,应单独设计。

兼容与降级边界

::scroll-button() 属于较新的 CSS 轮播能力,不应当成为唯一的可用路径。基础列表要先保证在没有伪元素支持时仍可横向滚动;箭头只是增强入口,不能通过隐藏滚动条、禁止触摸滑动或依赖唯一的点击事件来替代基础体验。

可以把增强样式放进能力查询,并保留容器本身的 overflow-x:auto:

@supports selector(.card-list::scroll-button(right)) {
  .card-list::scroll-button(left),
  .card-list::scroll-button(right) {
    /* 只有支持该选择器时,才启用增强按钮的布局和外观。 */
    display: inline-grid;
    place-items: center;
  }
}

@supports not selector(.card-list::scroll-button(right)) {
  .card-list {
    /* 不支持时继续提供可滚动区域,不伪造一个失效箭头。 */
    overflow-x: auto;
    scrollbar-width: auto;
  }
}

降级时最重要的结果不是“看起来仍有两个箭头”,而是用户仍然能发现列表可以横向移动。真实项目还应结合目标浏览器版本做兼容性决策,但不需要为了使用这个新伪元素重写整个轮播组件。

几个容易混淆的边界

问题应当怎样判断
按钮没有出现先确认选择器挂在滚动容器上,再确认对应 content 不是 none。
按钮出现但不能继续滚动检查内容是否真的超出容器,以及当前方向是否已经到达边界。
只显示箭头没有名称给 content 提供文本替代,并保留清晰的焦点轮廓。
不支持新特性怎么办保留 overflow-x:auto、触摸滚动和键盘路径,把按钮作为可选增强。

总结

给横向滚动列表添加原生箭头的关键是把职责分开:滚动容器负责产生可移动的内容范围,::scroll-button(left/right) 负责提供方向入口,content 负责触发生成并补充名称,:focus-visible 和 :disabled 负责让交互状态可感知。先保留基础滚动,再叠加这层 CSS 增强,兼容和可访问性会更稳。

相关问题

为什么只写 ::scroll-button(right) 没有按钮?因为生成伪元素还需要对应选择器的 content 为非 none,仅声明选择器不会自动创建控件。

::scroll-button() 和 ::scroll-marker 是一回事吗?不是。前者是滚动方向按钮,后者用于把子项或分页位置组织成滚动标记,两者解决的导航层级不同。

能不能完全隐藏横向滚动条?可以有视觉设计上的处理,但不应因此丢失触摸、键盘或其他可发现的滚动入口;新伪元素不支持时尤其要保留原生滚动。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
React useEffectEvent 怎样读取最新值而不重复注册副作用React useEffectEvent 怎样读取最新值而不重复注册副作用
上一篇
React useEffectEvent 怎样读取最新值而不重复注册副作用
CSS ::details-content 怎样给 details 折叠内容添加过渡
下一篇
CSS ::details-content 怎样给 details 折叠内容添加过渡
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    918次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    923次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1020次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1000次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    823次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码