壹 ❀ 引

故事的起因是这样的,某一个同事在封装了一个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结构,发现确实有滚动条的站位,尝试拖动,果然存在。那么现在我们可以得出两条结论:

  1. 滚动条一旦被隐藏,复原时需要重写它所有的属性样式,不然它会有站位但不可见。
  2. 我们前面的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开始选择,但是不包括classnewli,所以除了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】如何复原被隐藏的滚动条?记一个看似简单的样式问题所引发的一系列思考的更多相关文章

  1. 使用CSS隐藏元素滚动条

    如何隐藏滚动条,同时仍然可以在任何元素上滚动? 首先,如果需要隐藏滚动条并在内容溢出时显示滚动条,只需要设置overflow:auto样式即可.想要完全隐藏滚动条只需设置overflow:hidden ...

  2. CSS字体渐变 & 隐藏浏览器滚动条 & grid布局(转载)

    字体渐变  https://www.zhangxinxu.com/study/201104/css3-text-gradient-2.html 隐藏浏览器滚动条  https://blog.csdn. ...

  3. 移动端隐藏scroll滚动条::-webkit-scrollbar

    ::-webkit-scrollbar {/*隐藏滚轮*/ display: none; } CSS3自定义滚动条样式 -webkit-scrollbar 前言 webkit支持拥有overflow属 ...

  4. 小tip:CSS vw让overflow:auto页面滚动条出现时不跳动——张鑫旭

    小tip:CSS vw让overflow:auto页面滚动条出现时不跳动 这篇文章发布于 2015年01月25日,星期日,23:08,归类于 css相关. 阅读 46274 次, 今日 91 次 by ...

  5. 隐藏jqgrid滚动条

    .ui-jqgrid .ui-jqgrid-bdiv{ overflow-x: hidden; } /* 隐藏jqgrid滚动条 */

  6. css超出多行隐藏

      单行隐藏: overflow: hidden;/*超出部分隐藏*/ text-overflow:ellipsis;/* 超出部分显示省略号 */ white-space: nowrap;/*规定段 ...

  7. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

  8. WPF 自定义滚动条(ScrollView、ScrollBar)样式

    一.滚动条基本样式 本次修改Scrollview及ScrollBar滚动条样式是通过纯样式实现的.修改的内容包含滚动条的颜色,上下按钮的隐藏.另外添加了鼠标经过滚动条动画. style样式如下: &l ...

  9. 记一个社交APP的开发过程——基础架构选型(转自一位大哥)

    记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...

  10. 压缩网站的css和js,合并多个文件到一个文件

    压缩网站的css和js,合并多个文件到一个文件uglifyjs index.js html5shiv.min.js -o all.min.jsuglifycss index.min.css web.c ...

随机推荐

  1. java进阶(25)--泛型

    一.泛型基本概念 JDK5.0后新特性:Generic 1.不使用泛型举例

  2. [转帖]如何查看Docker容器环境变量,如何向容器传递环境变量

    https://www.cnblogs.com/larrydpk/p/13437535.html 1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 了解Docker容器的运行 ...

  3. [官方]华为的部分设备的SPECint_rate_2006的测试数据

    Test Sponsor System Name BaseCopies Processor Results EnabledCores EnabledChips Cores/Chip Threads/C ...

  4. Chrome 下载地址

    今天同事找到一个网页 感觉非常好用 这里保存并且推荐一下 https://www.chromedownloads.net/chrome64win-stable/

  5. vue数据不响应,可能是用法有问题

    <template> <div> <div> <span>用户名: {{ userInfo.name }}</span> <span& ...

  6. Unity Editor自定义菜单排序(MenuItem Order)

    扩展Unity的菜单MenuItem MenuItem 属性用于向主菜单和检视面板上下文菜单添加菜单项. 该 MenuItem 属性能够将任何静态函数转变为菜单命令,仅静态函数可使用 MenuItem ...

  7. TienChin 活动管理-活动状态完善

    修改字典 修改活动状态字典,将之前的数据键值为 0 的数据标签内容改为 过期: 更改下数据库的描述,禁用改为过期: ALTER TABLE `tienchin_activity` MODIFY COL ...

  8. 微信小程序-页面跳转Tabbar

    官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 首先我们 ...

  9. WebAssembly入门笔记[3]:利用Table传递引用

    在<WebAssembly入门笔记[2]>中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Momory面向单纯二进制字节的读写在使用起 ...

  10. 4.1 C/C++ 使用结构与指针

    C/C++语言是一种通用的编程语言,具有高效.灵活和可移植等特点.C语言主要用于系统编程,如操作系统.编译器.数据库等:C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统.图形用户界面 ...