做移动端H5页面的时候,横向滑动的商品列表、纵向滚动的评论区,一旦出现系统自带的滚动条,视觉上就会显得很粗糙。尤其是iOS和Android对滚动条的渲染样式不一致,很难通过统一调整让它们变得美观,所以干脆隐藏掉是最省事的做法。本文介绍几种隐藏滚动条的CSS方案,并且配合scroll-behavior属性实现平滑滚动效果,最后给出一段完整可用的示例代码。

一、为什么移动端要隐藏滚动条
移动端浏览器的滚动条和PC端不同,大部分情况下它只是一个短暂出现的指示条,滚动停止后会自动消失。但正因为它的出现和消失没有规律可循,在截屏、录屏或者演示的时候特别容易被抓到,影响页面观感。另外,像横向滑动卡片这种局部滚动区域,滚动条会占据几像素的高度,可能在容器底部形成一条缝隙,导致布局上出现细节问题。
还有一个常见的场景是轮播图或者滑动选择器。这类组件本身有自己的指示器,系统滚动条叠加上去就是重复的视觉元素,必须隐藏掉才能保证组件的纯粹性。所以隐藏滚动条并不是单纯为了好看,很多时候是产品层面的硬性要求。
需要特别注意的是,隐藏滚动条只是视觉上的处理,容器依然可以正常滚动,交互能力不受任何影响。这一点和overflow: hidden有本质区别,后者是彻底禁止滚动,千万别混淆。
二、隐藏滚动条的几种CSS写法
1. webkit内核专用方案
iOS的Safari、国内的各大安卓浏览器以及Chrome移动版,基本都是webkit内核,可以直接用伪元素来控制滚动条:
.scroll-container::-webkit-scrollbar {
display: none;
}这个写法的原理是把滚动条本身的渲染关闭,元素本身的滚动行为保留。::-webkit-scrollbar可以理解为滚动条整体容器,把它设为display: none之后,整条滚动条包括滑块和轨道都不会绘制。如果想保留滚动条但改样式,也可以针对::-webkit-scrollbar-thumb、::-webkit-scrollbar-track分别设置宽度和颜色。
需要注意的是,这个方案在Firefox上无效,因为Firefox不支持webkit前缀的伪元素。不过移动端Firefox的市场份额很小,如果只做移动端H5,基本可以忽略这个兼容性问题。
2. scrollbar-width标准属性方案
CSS标准提供了scrollbar-width属性,Firefox从68版本开始支持:
.scroll-container {
scrollbar-width: none; /* Firefox */
}这个属性接受的值有auto、thin和none。设为none就完全隐藏滚动条,thin是显示更细的滚动条。结合上面的webkit方案一起写,就能覆盖绝大多数浏览器:
.scroll-container {
-ms-overflow-style: none; /* 老版IE和Edge */
scrollbar-width: none; /* Firefox */
}
.scroll-container::-webkit-scrollbar {
display: none; /* webkit内核 */
}-ms-overflow-style是微软的私有属性,主要照顾老版本的IE和Edge浏览器,现在的项目如果不需要兼容它们,可以省略这一行。三行代码写在一起,就是目前最通用的隐藏滚动条组合。
3. 计算滚动的hack方案
还有一种老思路是把滚动条挤出可视区域:外层容器设置overflow: hidden并固定高度,内层元素负责滚动,滚动条宽度超出的部分被外层裁掉。这种方案需要精确计算滚动条宽度,在不同设备上表现不稳定,现在已经很少使用,除非遇到上面两种方案都失效的特殊内核浏览器,否则不推荐。
三、用scroll-behavior实现平滑滚动
隐藏滚动条解决了视觉问题,接下来是滚动手感。CSS的scroll-behavior属性有两个常用值:auto是默认的瞬间跳转,smooth则是平滑过渡。把它设置在滚动容器上:
.scroll-container {
scroll-behavior: smooth;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}scroll-behavior: smooth主要影响的是程序触发的滚动,比如锚点跳转、通过scrollTo方法滚到指定位置。用户手指滑动的物理滚动本身就有惯性,不受这个属性控制。所以它最常见的用途是点击导航后让页面平滑滚到对应区块,替代传统的JavaScript动画方案。
如果配合锚点使用,HTML结构里只要给目标元素设置id,点击链接即可平滑滚动:
<nav>
<a href="#section1">第一节</a>
<a href="#section2">第二节</a>
</nav>
<div class="scroll-container">
<section id="section1">内容一</section>
<section id="section2">内容二</section>
</div>这里的-webkit-overflow-scrolling: touch是iOS下的一个增强属性,开启后局部滚动区域会获得原生般的惯性滚动效果。不过在较新的iOS版本中,这个属性已经默认开启,写不写差别不大,但保留它可以兼容老设备。
还要注意一个细节:scroll-behavior: smooth不要设置在body或html上之后再叠加频繁的程序滚动,因为每次滚动都会触发过渡动画,用户连续操作时会有迟滞感。建议只在需要动画的场景下,通过JavaScript的scrollTo配合behavior参数按需启用:
container.scrollTo({
top: 300,
behavior: 'smooth'
});这种按需调用的方式更加灵活,也避免了对全局滚动行为产生副作用。
四、完整示例代码
下面给出一个横向图片列表的完整例子,实现隐藏滚动条加平滑滚动,可以直接复制到本地测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>隐藏滚动条示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 20px;
background: #f5f5f5;
}
/* 横向滚动列表 */
.card-list {
display: flex;
gap: 12px;
overflow-x: auto;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
}
/* webkit内核隐藏滚动条 */
.card-list::-webkit-scrollbar {
display: none;
}
.card {
flex: 0 0 140px;
height: 180px;
border-radius: 8px;
background: linear-gradient(135deg, #6a8dff, #a86bff);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
</style>
</head>
<body>
<div class="card-list">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
<div class="card">卡片4</div>
<div class="card">卡片5</div>
<div class="card">卡片6</div>
</div>
</body>
</html>在手机上打开这个页面,左右滑动卡片列表时不会出现任何滚动条,同时滚动过程带有系统原生的惯性效果。如果需要在点击按钮时让列表滚到某个位置,再通过scrollTo加behavior: smooth的方式调用即可,动画会自动接管滚动过程。
五、几个容易踩的坑
第一个坑是隐藏滚动条之后用户失去位置感知。对于内容很多的纵向滚动区域,完全没有滚动指示可能让用户不知道还有更多内容。解决办法是自定义一个进度条元素,通过监听scroll事件计算滚动比例,用JavaScript更新进度条宽度,既保留了美观又不牺牲可用性。
第二个坑是把scroll-behavior: smooth用在所有容器上。前面提到过,程序触发的滚动都会变成动画,比如下拉刷新后重置滚动位置的场景,平滑动画反而显得拖沓。原则上只在有明确交互意图的滚动上使用,其他场景保持默认。
第三个坑是性能问题。移动端长列表滚动卡顿通常和滚动条无关,更多是DOM节点过多或者图片未做懒加载导致的。不要指望隐藏滚动条能提升滚动性能,该做的虚拟列表优化、图片压缩一样都不能少。把这几点都想清楚,隐藏滚动条加平滑滚动的方案才能真正落地到生产环境。