Skip to content

一文读懂 CSS 自定义滚动条

2487字约8分钟

css

2023-03-05

有时候,为了保持我们的应用程序 UI 交互体验在不同系统的一致性,需要覆盖默认的滚动条, 通过自定义滚动条的方式,获得更好的用户体验。

scrollbar intro
scrollbar intro

滚动条的组成

首先,需要了解 滚动条由哪些部分组成的。

滚动条主要包含两个部分: 滚动轨道 Track滑块 Thumb

scrollbar parts
scrollbar parts

Track 是滚动条的底部, Thumb 是提供用户交互的, 当用户拖动它控制页面或容器的滚动内容。

滚动条可以出现在 水平 或者 垂直 方向,而且在 多语言环境下,也会随着 从左到右 LTR 和 从右到左 RTL
而变化。

scrollbar places dir
scrollbar places dir

自定义滚动条

在过去,能够进行 自定义滚动条的, 只有 基于 webkit 内核的浏览器 得到了支持,而像 FirefoxIE 浏览器则不具备 自定义滚动条 的能力。但是,对于 Firebox, CSS 有了新的语法帮助我们完成滚动条的自定义。

我将分别介绍 webkit 下的旧的语法,然后是 新的语法。

旧的语法

滚动条宽度

首先,我们需要定义滚动条的大小,它可以是垂直滚动条的宽度,也可以是水平滚动条的高度。

.container::-webkit-scrollbar {
  width: 10px;
}

然后,我们就可以开始自定义滚动条的样式了。

滚动条 Track

Track 表示滚动条的底部,我们可以通过添加 background-colorbox-shadowborder-radiusborder 来控制 Track 的样式。

.container::-webkit-scrollbar-track {
  background-color: darkgrey;
}

滚动条 Thumb

准备好 滚动条的底部后,我们还需要设置滚动条 Thumb 的样式。用户可以拖动 Thumb 来与滚动条进行交互。

.container::-webkit-scrollbar-thumb {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}

旧语法浏览器兼容

@caniuse

至此,我们已经介绍了 CSS 中设置 自定义滚动条的旧语法以及兼容性。 接下来,我们将介绍 CSS 中设置 自定义滚动条的新语法。

新语法

滚动条宽度

这定义了滚动条宽度,我们需要关注的值是 autothin 。 需要注意的是,我们无法像 webkit 语法那样定义一个特定的数字。

.section {
  scrollbar-width: thin;
}

滚动条颜色

使用此属性,我们可以将滚动条 TrackThumb 的颜色定义为成对的值。

.section {
  scrollbar-color: #6969dd #e0e0e0;
}

尽管这种语法很简单,但是我们只能使用 纯色,无法添加 阴影、渐变、圆角边框 等其他相关的样式。

滚动条装订线 Gutter

你有没有想过,当内容在滚动容器中增加时,我们如何避免布局变化?让我们以以下案例为例。

scrollbar gutter
scrollbar gutter
.box {
  padding: 1rem;
  max-height: 220px;
  overflow-y: auto;
}

我们有一个四周都有 1rem 的内边距的容器。到目前为止,内容很短,滚动条不会显示,因为使用了 overflow-y: auto

当我们使用 overflow-y: auto ,当内容很短时不会显示滚动条,直到内容超过了容器的高度,滚动条才显示。

当内容增长时,将显示滚动条,从而减少内容的可用空间。

scrollbar gutter
scrollbar gutter

可以看到,当内容过长出现滚动条时,内容会发生偏移。 这是由于浏览器为滚动条保留了一个空间,导致内容空间收到挤压变小。

但幸运的是,现在可以通过 scrollbar-gutter 属性来解决这个问题。它帮助为滚动条提前预留足够的空间。 它的默认值为 auto,可选值有 stableboth-edges

.box {
  padding: 1rem;
  max-height: 220px;
  overflow-y: auto;
  scrollbar-gutter: stable;
}
scrollbar gutter
scrollbar gutter

当内容增加时,就不会影响布局的空间变化,因为浏览器已经为 滚动条预留了空间。

scrollbar gutter
scrollbar gutter

好消息是,scrollbar-gutter 的兼容性,从 Chrome@94 就开始得到了支持。

新语法浏览器兼容

@caniuse

自定义滚动条的使用范围

有一点需要考虑的,我们的 自定义滚动条,它应该在哪里生效。 是希望所有的 可滚动的元素都应用 自定义滚动条,还是只有特定的元素应用自定义滚动条呢。

所有可滚动元素

对于 旧的语法, 想要使所有 可滚动元素都 生效,我们可以直接编写 选择器,而无需将它们附加到元素。

::-webkit-scrollbar {
  width: 10px;
}

::-webkit-scrollbar-track {
  background-color: darkgrey;
}

::-webkit-scrollbar-thumb {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}

而对于新语法,只需要将它们 应用于 <html> 元素即可

html {
  scrollbar-color: #6969dd #e0e0e0;
  scrollbar-width: thin;
}

特定可滚动元素

对于 旧的语法,想要使特定的 可滚动元素生效,我们在特定元素之后编写 选择器。

.container::-webkit-scrollbar {
  width: 10px;
}

.container::-webkit-scrollbar-track {
  background-color: darkgrey;
}

.container::-webkit-scrollbar-thumb {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}

对于新语法,也是是相同的。

.container {
  scrollbar-color: #6969dd #e0e0e0;
  scrollbar-width: thin;
}

设计自定义滚动条

在深入研究 自定义滚动条之前,首先需要了解 默认的滚动条的样式。

默认的滚动条在 不同的操作系统之中是不同的。

在 MacOS Safari 中, Track 两侧都有边框, 背景色为纯色,Thumb 是圆形的,左右两侧都有空间。

scrollbar use case
scrollbar use case

而在 MacOS Chrome 中,Track 是透明的,Thumb 是原型的,而且整个滚动条只在滚动时才显示,且不占据空间。

在 Windows 中,Track 是 灰色背景,Thumb 是 矩形的。

scrollbar use case
scrollbar use case

示例1

以下是根据上面的模型,自定义的滚动条

.container::-webkit-scrollbar {
  width: 16px;
}

.container::-webkit-scrollbar-track {
  background-color: #e4e4e4;
  border-radius: 100px;
}

.container::-webkit-scrollbar-thumb {
  background-color: #d4aa70;
  border-radius: 100px;
}

TrackThumb 添加 border-radius 是必要的,因为 border-radius 无法在 ::-webkit-scrollbar 上生效。

如果是使用的 新的语法,我们不能调整 滚动条的宽度,能做的事情只有设置 TrackThumb 的颜色:

.container {
  scrollbar-color: #d4aa70 #e4e4e4;
}

注意

以下示例仅适用于 webkit 内核的浏览器。对于实际项目,你还可以同时添加新的语法支持 Firefox

示例2:阴影+渐变

在这个示例中,我们给滚动条添加了 阴影 和 渐变。来看看效果如何:

.container::-webkit-scrollbar-thumb {
  background-image: linear-gradient(180deg, #d0368a 0%, #708ad4 99%);
  box-shadow: inset 2px 2px 5px 0 rgba(#fff, 0.5);
  border-radius: 100px;
}

渐变

示例3: 带边框

我们还可以为 TrackThumb 添加 边框,这可以帮助我们解决一些棘手的设计。

.container::-webkit-scrollbar-thumb {
  border-radius: 100px;
  background: #8070d4;
  border: 6px solid rgba(0, 0, 0, 0.2);
}

基于相同的示例,我们还可以调整 Thumb 的 边框,获得一些有趣的效果。

.container::-webkit-scrollbar-thumb {
  border-radius: 100px;
  background: #8070d4;
  border: 6px solid rgba(0, 0, 0, 0.2);
  border-left: none;
  border-right: none;
}

示例4:Thumb 带间隔

在此示例中,我们希望 Thumb 的四周与 Track 都带有一定的间隔。 由于它无法与 滚动条一起使用 padding。 因此我们需要使用 borderbackground-clip 实现效果。

.container::-webkit-scrollbar-thumb {
  border: 5px solid transparent;
  border-radius: 100px;
  background-color: #8070d4;
  background-clip: content-box;
}

Thumb 带间隔

增加 hover 效果

我们可以为 滚动条添加 hover 效果吗?

是的, 可以。我们可以为 新旧的语法添加 hover 效果。

/* 旧语法 */
.section::-webkit-scrollbar-thumb:hover {
  background-color: #5749d2;
}

/* 新语法 */
.section {
  scrollbar-color: #d4aa70 #e4e4e4;
  transition: scrollbar-color 0.3s ease-out;
}

.section:hover {
  scrollbar-color: #5749d2;
}

同时,在使用新语法上,我们还可以添加 过渡效果,但是在 旧语法 上则不支持。

hover 效果

在需要时显示滚动条

通过向 overflow 属性添加值以外的 visible 值,可以创建可滚动元素。 建议使用关键字, auto 因为它只会在内容超出其容器时显示滚动条。

.container {
  overflow: auto;
}

Keep It Simple

公告板标题

更新说明

  • 新增了一些功能
  • 修复了一些 bug