深入剖析浏览器滚动条

深入剖析浏览器滚动条为什么要专门写一篇关于浏览器滚动条的文章呢?毕竟定制滚动条属于小众需求。事情源于一次产品上线之后,用户反馈滚动条也太丑了,设计让前端帮忙改一下。

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

前言

为什么要专门写一篇关于浏览器滚动条的文章呢?毕竟定制滚动条属于小众需求。事情源于一次产品上线之后,用户反馈滚动条也太丑了,设计让前端帮忙改一下:要细一些,宽度6px,颜色淡一些,#000000 8%不透明度,hover状态时宽度 10px,颜色 #000000 16%不透明度

于是借此机会对滚动条做了一番研究,发现这里面的水还是很深的(网上的文章很多关于滚动条的文章都是纰漏百出,人云亦云),在此我把研究结果向大家分享一下,一个小小的滚动条中竟然包含了以下六种伪元素

  • ::-webkit-scrollbar——整个滚动区域
  • ::-webkit-scrollbar-button——滚动条两端的按钮(包含上下箭头)
  • ::-webkit-scrollbar-track——滚动条外层轨道
  • ::-webkit-scrollbar-track-piece——滚动条内层轨道(分为上下两部分)
  • ::-webkit-scrollbar-thumb——可拖动的滑块
  • ::-webkit-scrollbar-corner——垂直滚动条和水平滚动条交汇部分(通常在右下角)

可以用下面的一张图来描述上述所有元素:

深入剖析浏览器滚动条

看起来是不是很复杂?别担心,我会从下面这个基础的原生滚动条开始,带领大家一步步认识上面的各种伪元素:

深入剖析浏览器滚动条

上面矩形滚动区域的 HTML 结构为:

<div class="container">
  <div class="rect">
    <div class="box"></div>
  </div>
</div>

初始 CSS 样式为:

.container {
  margin-top: 50px;
  display: flex;
  justify-content: space-around;
}

.rect {
  width: 600px;
  height: 600px;
  overflow: scroll;
  border: 1px solid gainsboro;
}

.box {
  width: 1000px;
  height: 1000px;
  background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
  background-size: 42.4264px 42.4264px;
  opacity: 0.2;
}

-webkit-scrollbar 伪元素

::-webkit-scrollbar代表整个滚动条,我们可以为其设置宽高、背景色、边框,例如:

.rect::-webkit-scrollbar {
  width: 50px;
  height: 50px;
  background-color: yellow;
  border: 5px solid green;
}

然后滚动条就变成了下面这个样子:

深入剖析浏览器滚动条

值得注意的是,对于自定义滚动条样式,这个伪类是必不可少的,如果没有设置 ::-webkit-scrollbar,那么下面所有其他的伪类都无法生效。所以该伪类的一个重要的作用就是告诉控制 webkit 引擎是否使用默认的滚动条样式。

另外需要特别强调的是,在 -webkit-scrollbar 伪类样式中,width 属性只对垂直滚动条起作用,height 属性只对水平滚动条起作用,而这个规则对下面的 -webkit-scrollbar-button则恰恰相反。

-webkit-scrollbar-button 伪元素

::-webkit-scrollbar-button伪元素表示滚动条两端的按钮区域。如果是垂直滚动条,按钮在上下两端;如果是水平滚动条,按钮在左右两端。该伪元素要配合以下六个伪类一起使用:

伪类 选中的状态
:horizontal 当滚动条处于水平方向
:vertical 当滚动条处于垂直方向
:decrement 当点击后减少滚动值
:increment 当点击后增加滚动值
:start 当处于开始位置
:end 当处于结束位置

我们增加以下 CSS 代码来设置滚动按钮样式:

.rect::-webkit-scrollbar-button {
  display: block;
  background-color: rgba(185, 28, 28, 0.8);
  background-repeat: no-repeat;
  background-size: 50%;
  background-position: center;
  height: 25px;
  width: 25px;
}

.rect::-webkit-scrollbar-button:vertical:start:increment {
  background-image: url("https://img.zlib.cn/blog/chevron-down.svg");
}

.rect::-webkit-scrollbar-button:vertical:start:decrement {
  background-image: url("https://img.zlib.cn/blog/chevron-up.svg");
}

.rect::-webkit-scrollbar-button:vertical:end:increment {
  background-image: url("https://img.zlib.cn/blog/chevron-down.svg");
}

.rect::-webkit-scrollbar-button:vertical:end:decrement {
  background-image: url("https://img.zlib.cn/blog/chevron-up.svg");
}

.rect::-webkit-scrollbar-button:horizontal:start:increment {
  background-image: url("https://img.zlib.cn/blog/chevron-right.svg");
}

.rect::-webkit-scrollbar-button:horizontal:start:decrement {
  background-image: url("https://img.zlib.cn/blog/chevron-left.svg");
}

.rect::-webkit-scrollbar-button:horizontal:end:increment {
  background-image: url("https://img.zlib.cn/blog/chevron-right.svg");
}

.rect::-webkit-scrollbar-button:horizontal:end:decrement {
  background-image: url("https://img.zlib.cn/blog/chevron-left.svg");
}

效果如下:

深入剖析浏览器滚动条

刚才上面也讲到,在 -webkit-scrollbar-button伪元素里面,width 只对水平滚动条两端的按钮起作用,height 只对垂直滚动条两端的按钮起作用。

-webkit-scrollbar-track 伪元素

::-webkit-scrollbar-track表示滚动条的外层轨道,我们先给它增加以下 CSS 代码看看效果:

.rect::-webkit-scrollbar-track {
  background-color: blue;
  border: 5px solid orange;
  margin: 30px;
}

这里特地增加了 margin 外边距把 scrollbar 本身的背景色给透出来方便大家观察其位置:

深入剖析浏览器滚动条

上面的蓝色背景橙色边框区域就是外层轨道的,需要注意的是,这里无法单独对其设置 width 或 height 样式,它的宽高始终和 -webkit-scrollbar的宽高保持一致。既然是外层轨道,说明存在内层轨道,我们继续往下看:

-webkit-scrollbar-track-piece 伪元素

::-webkit-scrollbar-track-piece滚动条的内层轨道,这个就有点意思了,为了看起来更有辨识度,我们用颜色区分出来:

.rect::-webkit-scrollbar-track-piece {
  background-color: green;
  border: 5px solid purple;
  margin: 30px;
}

细心的你可能已经发现了,这次的样式非常奇怪,因为中间有一道杠:

深入剖析浏览器滚动条

这是因为内层轨道其实是有两部分组成的,垂直滚动条的内层轨道被分为上下部分,水平滚动条的内层轨道被分为左右两部分,而每一部分都可以用 startend伪类来控制,例如设置不同的背景色:

/* 控制滚动区域的上/左半部分 */
.rect::-webkit-scrollbar-track-piece:start {
  background-color: yellowgreen;
}

/* 控制滚动区域的下/右半部分 */
.rect::-webkit-scrollbar-track-piece:end {
  background-color: greenyellow;
}

通过设置背景色区分,可以看到更明显的看到上下/左右两部分的范围了:

深入剖析浏览器滚动条

-webkit-scrollbar-thumb 伪元素

::-webkit-scrollbar-thumb才是滚动条的滑块,也就是可拖动的部分,我们用下面的 CSS 把它展现出来:

.rect::-webkit-scrollbar-thumb {
  background-color: rgba(128, 0, 128, 0.5);
  border-radius: 30px;
}

可以看到滚动滑块的中间恰好是内层轨道上下/左右两部分的交界处:

深入剖析浏览器滚动条

这里有一点需要特别注意,很多人想通过 width 来修改垂直滑块的宽度,或者通过 height 来修改水平滑块的高度,其实都是不可行的,因为它的宽高永远和 -webkit-scrollbar保持一致,那怎样从视觉上让其变得更窄一点呢?这里要用到 background-clip这个 CSS 属性:

background-clip 用于设置元素的背景(包括背景颜色或背景图片)是否延伸到边框、内边距盒子和内容盒子下面。

它可以有以下取值:

  • background-clip: border-box:背景延伸至 border 外沿
  • background-clip: padding-box:背景延伸至 padding 外沿
  • background-clip: content-box:背景延伸至 content 外沿
  • background-clip: text:背景剪裁成文字的前景色

我们给滚动滑块设置边框透明和背景范围:

.rect::-webkit-scrollbar-thumb {
  background-color: rgba(128, 0, 128, 0.5);
  border-radius: 30px;

  border: 15px solid transparent; /* 设置边距透明 */
  background-clip: padding-box; /* 设置背景范围 */
}

可以看到从视觉上看滚动滑块的宽度/高度发生了改变:

深入剖析浏览器滚动条

-webkit-scrollbar-corner 伪元素

::-webkit-scrollbar-corner垂直滚动条和水平滚动条交界的部分,我们可以单独控制其样式,例如添加背景色:

.rect::-webkit-scrollbar-corner {
  background-color: #7f1d1d;
}

注意看到右下角区域的变化:

深入剖析浏览器滚动条

学习总结

讲完这六个伪元素,再回过来看下面的图,就非常清晰了:

深入剖析浏览器滚动条

可以看到滚动条在设计上是非常复杂的,但正因为此,才可以满足更多的个性化定制需求,虽然带有 -webkit-前缀,不是 w3c 标准,但是由于 Chrome 一统天下,这已经成为事实上的浏览器标准了。

实战

再回到最初的需求:要细一些,宽度6px,颜色淡一些,#000000 8%不透明度,hover状态时宽度 10px,颜色 #000000 16%不透明度。假设现在滚动区域是一个类为 rect 的 div,结构如下:

<div class="rect">
  <!-- 滚动区域 -->
</div>

最初写的 CSS 代码如下:

.rect::-webkit-scrollbar {
  width: 6px;
  height: 0;
  background-color: transparent;
}

.rect::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.08);
}

.rect::-webkit-scrollbar-thumb:hover {
  width: 10px;
  background-color: rgba(0, 0, 0, 0.16);
}

结果发现滚动条的颜色生效了,但是 hover 上去之后宽度并没有变宽,这是因为为 -webkit-scrollbar-thumb单独设置宽度是无效的,必须借用 background-clip来实现类似效果:

.rect::-webkit-scrollbar {
  width: 10px;
  height: 0;
  background-color: transparent;
}

.rect::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.08);
  border-left: 4px solid transparent;
  background-clip: padding-box;
}

.rect::-webkit-scrollbar-thumb:hover {
  background-color: rgba(0, 0, 0, 0.16);
  border: 0;
}

最终效果如下:

深入剖析浏览器滚动条

今天的文章深入剖析浏览器滚动条分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/20230.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注