【CSS】如何复原被隐藏的滚动条?记一个看似简单的样式问题所引发的一系列思考

壹 ❀ 引
故事的起因是这样的,某一个同事在封装了一个TableList
组件,用于做表格视图渲染,但出于研发经验考虑上,他可能觉得表格若出滚动条可能会引发某些不可预估的小问题(毕竟一个基础组件会被用于很多地方),省掉滚动条也避免很多宽度不够的适配问题,于是选择了暴力做法,直接在组件样式中隐藏了双向滚动条...
// 滚动条有两个方向,width隐藏纵向,height隐藏横向
.scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
}
但事实上对于纵向都还好,用户能感知到有内容被页面遮住了,即便看不到滚动条,也可以利用鼠标滚轮控制上下滚动。可是鼠标又不能横向滚动,这让没触摸板的PC用户怎么玩?于是就有客户提单,说XX页面的XX功能横向缺少滚动条无法滚动(鼠标没滚动条拖动),内容看不全。看似挺简单的问题,引发了一系列的坑,以及触碰到了我对于滚动条的知识盲区,那么本文做个简单的记录。
贰 ❀ 隐藏的滚动条如何恢复默认
我将通过一个例子来演示这个过程,比如下面这段代码展示了一个滚动条被隐藏的表格,因为我电脑有触摸板,所以还是可以通过手势进行拖拽:
<div id="test" class="scroll">
<table border="1">
<tr>
<th>Month</th>
<th>Savings</th>
<th>User</th>
</tr>
<tr>
<td>January</td>
<td>$100</td>
<td>Echo</td>
</tr>
</table>
</div>
#test::-webkit-scrollbar {
width: 0;
height: 0;
}
div.scroll {
margin: 20px auto;
height: 100px;
width: 130px;
overflow: auto;
}

既然滚动条是因为宽高都没了,那我让这个样式不生效不就好了,直接复写样式进行覆盖:
#test::-webkit-scrollbar {
width: unset;
height: unset;
}
刷新页面,然后让我产生了两个疑惑点,第一,滚动条并未出现,第二,样式怎么没有覆盖的痕迹:

正常来说,样式覆盖是会有中划线表示这条样式没起作用,比如我们覆盖宽度,你会发现生效的样式在上,被覆盖的样式被划掉了

难道用unset
不行?或者权重不够?带着疑惑我将unset
替换成具体的数值,升值在后面加上了!important
:
#test::-webkit-scrollbar {
width: 12px !important;
height: 12px !important;
}
刷新页面,滚动条依旧没出现,样式也没有出现中划线,这下确实是有点触碰我知识盲区了,毕竟以前大部分场景都是做隐藏滚动条的活,这下来个还原滚动条的操作居然把我整不会了...
带着疑惑我去问了下前端大佬,毕竟他阿里8年开发经验,我想着总比我见多识广,结果他又把我想到的可能性又重试了一遍,然后一脸疑惑的看着我,也蒙圈了....然后他说了一句我非常认可以及极有帮助的话,当你对一个问题非常疑惑的时候,那说明你不够了解它,这时候你就应该去补充对应的知识,而不是继续盲目的尝试。于是我打开了::-webkit-scrollbar的MDN,也了解到除了能让滚动条隐藏外,其实还有定义滚动条滑块,滚动轨道等等滚动条属性:
::-webkit-scrollbar
— 整个滚动条.::-webkit-scrollbar-button
— 滚动条上的按钮 (上下箭头).::-webkit-scrollbar-thumb
— 滚动条上的滚动滑块.::-webkit-scrollbar-track
— 滚动条轨道.::-webkit-scrollbar-track-piece
— 滚动条没有滑块的轨道部分.::-webkit-scrollbar-corner
— 当同时有垂直滚动条和水平滚动条时交汇的部分.::-webkit-resizer
— 某些元素的corner部分的部分样式(例:textarea的可拖动按钮).
处于好奇,我在样式中又添加了如下样式:
// 为滚动滑块添加背景色
#test::-webkit-scrollbar-thumb{
background-color: #e4393c;
}

奇迹出现了,现在多了一个红色的滑动块,我们可以拖动滚动条了,我突然恍然大悟!!在我设置unset
时会不会滚动条其实存在了,但它无色无形我才没能感知到它的存在。
于是我去除了滑动块的颜色,查看了DOM结构,发现确实有滚动条的站位,尝试拖动,果然存在。那么现在我们可以得出两条结论:

- 滚动条一旦被隐藏,复原时需要重写它所有的属性样式,不然它会有站位但不可见。
- 我们前面的
unset
样式覆盖其实有生效,滚动条样式覆盖很特殊,它不会有删除线。
结论虽然有了,但仍然不符合我的预期,我是希望取消隐藏后滚动条自己就恢复默认,但现在很明显我得把所有样式都复写一遍,这是我不愿意做的,当然到这里也要说一句,千万不要在一个高度复用的基础组件中写这种不可逆转的样式,真的很折磨人!!
叁 ❀ 让隐藏滚动条成为组件的可选配置
由于复写滚动条样式过于麻烦,这里我不得不想想其它更优的做法,此时脑袋中就蹦出了选择器:not()
,由于组件是嵌入在一个个不同页面的,所以不同页面总会有一些特化的class
,于是我就想到通过特化class
配合:not()
来让此页面的组件不要生效滚动条。但我有很长一段时间没写样式了,所以对于not
选择器居然有点陌生,这里做个简单复习:
<ul>
<li class="new">1</li>
<li>2</li>
<li>3</li>
</ul>
li:not(.new) {
color: orange;
}

这应该是一个最基础的not
选择器例子了,从li
开始选择,但是不包括class
是new
的li
,所以除了1之外,其余都是橘色。
我们来看第二个例子,可能这个例子会轻量颠覆你对于此选择器的认知:
<body>
<p>我是p标签</p>
<span class="span">我是span标签</span>
</body>
:not(p){
color: #e4393c;
}

哎?奇了怪了,我们样式明明写的是除了p
标签之外的所有元素颜色是红色,那为什么p
元素也是红色,查看一眼控制台的样式属性,inherited from body
,啥意思?p
标签的颜色继承于body
,也就是说样式确确实实是过滤了p
,但是它会对p
标签的父级body
生效,而颜色是可以继承的,最终导致p
继承了body
的颜色。

假设我们给p
额外定义一个不同的颜色,情况就符合预期了:
p{
color: orange;
}
:not(p){
color: #e4393c;
}

所以到这里你会发现,not
用于解决同级元素(比如上面的为li过滤部分特殊的li)非常好用,但如果not
用于过滤全局的部分元素,那你就得考虑样式继承带来的额外影响,而我在解决项目问题时,肯定不能用全局过滤,可行的肯定是利用同级class
来过滤,结果看了一眼并没有什么特化的同级类型,于是我又陷入了沉思....
这个问题的根本原因,就是同事偷懒写了一个不可逆转的样式,那我何不将这个样式作为此组件的一个属性呢?考虑到这个组件在其它地方也有使用,所以修改思路是隐藏滚动条默认开关是true
,而需要隐藏的地方在外层传递flase
即可,而只有在开关是true
时才会在这个组件上添加一个同名class
,然后再在样式中结合not
让不需要隐藏滚动条的地方不要生效,大概思路是:
// 组件定义处
className={classnames("table-list", { 'show-scroll-bar': this.props.isShowScrollBar })}
// 使用组件的地方
<Component isShowScrollBar>
//样式部分,有show-scroll-bar这个class的table组件不会隐藏滚动条
.table-list:not(.show-scroll-bar) {...}
那么到这里,我们既没有影响现有组件在其它页面的表现,也没有很麻烦的复写滚动条默认样式,同时也为组件增加了一个开启和关闭隐藏滚动条的自选配置,一举多得,此问题就告一段落了。
肆 ❀ 总
其实单站在解决问题的角度,暴力复写其实早就解决了,只是在追求一个更小影响更巨接受度的做法上,对方案进行了多次探索与推翻。所以明明是一个样式问题,但由于我对于滚动条的陌生以及部分基础知识的遗忘,这个问题我足足玩了一天....
但事实上,我们在定义一个基础组件时,确实不应该在组件内部定义一些外部很难复写的样式,或者很难扭转的逻辑,这会很让后续的开发异常头疼,当然我猜测,写这块的作者估计也不会想到滚动条复原会如此麻烦。
杂记 ❀ 迫于无奈,我吃了别人女友点的外卖
分享一个今天让我啼笑皆非的故事。由于今晚公司有一个大版本需要发布,所有研发都需要待命,所以晚6点的时候我点了一份外卖。因为疫情影响,外卖是没办法送上楼的,大楼物业也是在楼下安置了按楼层划分的桌子用于放外卖。考虑到晚上点外卖的人并不多,所以我也是不慌不忙等了好一会才下去取,当走到桌子前我傻眼了,9-15楼的桌子上一共三份外卖,反反复复看了四遍,确认过眼神,我是外卖被偷的人!!
但我又考虑到可能是外卖小哥放错了,于是立马给小哥打了个电话,当小哥精确说出我所点的外卖店家名称后,我确信他没放错,外卖确实是被人拿走了。小哥说让我等等,等他回来确认下再找大楼调监控,我想着也就20块钱的事,就不用那么麻烦了,大家都是打工人也第都不容易,赔偿就不用了,只是今晚,这个世界多了一个饿肚子的人。
当我走进电梯后来了一个陌生电话,我原以为是外卖小哥打过来告诉我外卖真的放错了,不禁内心狂喜!!!接通后,对方就是那个拿错外卖并已经吃完的人....他说他跟我同姓,然后我和他的公司只相隔一层,所以我俩的外卖在同一个桌子,晚上他也没多想,看到姓氏正确就拿上去吃掉了,吃完了才发现吃错了外卖,跟我道歉的同时表示要赔偿我,并把他的外卖给我吃。我说赔偿就不必了,把你的饭给我吃就行;他让我在15楼等会,出于歉意,他会帮我送上来。
电话挂断后我心里一想,不对啊,自己点的外卖自己难道不清楚吗,怎么吃完才发现,这什么脑回路...但又一想到有饭吃就行了,不管那么多了,等了一会后,电话另一头的人真的送外卖上来了,他说他的外卖是他女朋友帮他点的,所以其实他也不知道具体点的什么,吃完了才发现号码不对。我接过外卖一看,我自己点的拌饭,他女朋友给他点的也是拌饭,只是店家不同,而且我俩一个姓,拿错也确实情有可原了。

迫于无奈,我吃了她女朋友点给他的外卖,但不得不说,45一顿的外卖还真就比20一顿的要香!虽然吃外卖的时候,被迫还吃了一顿狗粮。
PS:封面原图地址
【CSS】如何复原被隐藏的滚动条?记一个看似简单的样式问题所引发的一系列思考的更多相关文章
- 使用CSS隐藏元素滚动条
如何隐藏滚动条,同时仍然可以在任何元素上滚动? 首先,如果需要隐藏滚动条并在内容溢出时显示滚动条,只需要设置overflow:auto样式即可.想要完全隐藏滚动条只需设置overflow:hidden ...
- CSS字体渐变 & 隐藏浏览器滚动条 & grid布局(转载)
字体渐变 https://www.zhangxinxu.com/study/201104/css3-text-gradient-2.html 隐藏浏览器滚动条 https://blog.csdn. ...
- 移动端隐藏scroll滚动条::-webkit-scrollbar
::-webkit-scrollbar {/*隐藏滚轮*/ display: none; } CSS3自定义滚动条样式 -webkit-scrollbar 前言 webkit支持拥有overflow属 ...
- 小tip:CSS vw让overflow:auto页面滚动条出现时不跳动——张鑫旭
小tip:CSS vw让overflow:auto页面滚动条出现时不跳动 这篇文章发布于 2015年01月25日,星期日,23:08,归类于 css相关. 阅读 46274 次, 今日 91 次 by ...
- 隐藏jqgrid滚动条
.ui-jqgrid .ui-jqgrid-bdiv{ overflow-x: hidden; } /* 隐藏jqgrid滚动条 */
- css超出多行隐藏
单行隐藏: overflow: hidden;/*超出部分隐藏*/ text-overflow:ellipsis;/* 超出部分显示省略号 */ white-space: nowrap;/*规定段 ...
- vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结
vue—你必须知道的 目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...
- WPF 自定义滚动条(ScrollView、ScrollBar)样式
一.滚动条基本样式 本次修改Scrollview及ScrollBar滚动条样式是通过纯样式实现的.修改的内容包含滚动条的颜色,上下按钮的隐藏.另外添加了鼠标经过滚动条动画. style样式如下: &l ...
- 记一个社交APP的开发过程——基础架构选型(转自一位大哥)
记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...
- 压缩网站的css和js,合并多个文件到一个文件
压缩网站的css和js,合并多个文件到一个文件uglifyjs index.js html5shiv.min.js -o all.min.jsuglifycss index.min.css web.c ...
随机推荐
- java进阶(25)--泛型
一.泛型基本概念 JDK5.0后新特性:Generic 1.不使用泛型举例
- [转帖]如何查看Docker容器环境变量,如何向容器传递环境变量
https://www.cnblogs.com/larrydpk/p/13437535.html 1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 了解Docker容器的运行 ...
- [官方]华为的部分设备的SPECint_rate_2006的测试数据
Test Sponsor System Name BaseCopies Processor Results EnabledCores EnabledChips Cores/Chip Threads/C ...
- Chrome 下载地址
今天同事找到一个网页 感觉非常好用 这里保存并且推荐一下 https://www.chromedownloads.net/chrome64win-stable/
- vue数据不响应,可能是用法有问题
<template> <div> <div> <span>用户名: {{ userInfo.name }}</span> <span& ...
- Unity Editor自定义菜单排序(MenuItem Order)
扩展Unity的菜单MenuItem MenuItem 属性用于向主菜单和检视面板上下文菜单添加菜单项. 该 MenuItem 属性能够将任何静态函数转变为菜单命令,仅静态函数可使用 MenuItem ...
- TienChin 活动管理-活动状态完善
修改字典 修改活动状态字典,将之前的数据键值为 0 的数据标签内容改为 过期: 更改下数据库的描述,禁用改为过期: ALTER TABLE `tienchin_activity` MODIFY COL ...
- 微信小程序-页面跳转Tabbar
官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 首先我们 ...
- WebAssembly入门笔记[3]:利用Table传递引用
在<WebAssembly入门笔记[2]>中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Momory面向单纯二进制字节的读写在使用起 ...
- 4.1 C/C++ 使用结构与指针
C/C++语言是一种通用的编程语言,具有高效.灵活和可移植等特点.C语言主要用于系统编程,如操作系统.编译器.数据库等:C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统.图形用户界面 ...