问题
不管是 MacOS 还是 Window 系统,其浏览器的滚动条会挤占原本的宽度,导致元素的位置发生变化
测试代码如下
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>scroll bar</title>
<style>
div {
margin: 100px auto;
width: 200px;
height: 300px;
border: 1px solid #000;
resize: vertical;
overflow: auto;
}
p {
width: 100%;
height: 160px;
background-color: yellowgreen;
}
</style>
</head>
<body>
<div>
<p></p>
</div>
</body>
</html>
录屏效果如下
当容器的高度发生变化时,滚动条会挤占元素的宽度,元素的位置会发生变化,最终影响用户体验
看起来这是样式问题,那么有没有对应的 CSS 样式解决这个问题呢?没错! overflow: overlay
就是用来解决这个问题
overflow: overlay
overflow: overlay
是 CSS 中的一个属性值,用于指定一个元素在内容溢出时如何处理滚动。与传统的 overflow: auto
或 overflow: scroll
不同,overflow: overlay
会在内容溢出时显示滚动条,但它会覆盖在内容上方,而不会改变容器的尺寸。
这个属性值特别有用的情况是在 macOS 的 Safari 浏览器中。在 macOS 中,滚动条默认是隐藏的,只有在用户滚动内容时才会显示出来。然而,传统的滚动条会占据内容的空间,可能影响布局。使用 overflow: overlay
可以让滚动条在内容溢出时显示,但不会占据实际内容的空间,这样可以更好地保持布局的稳定性和一致性。
总的来说,overflow: overlay
解决了在 macOS Safari 中使用隐藏滚动条时可能出现的布局问题,让开发者能够更好地控制滚动行为,并提供更一致的用户体验。
但但但但但但但但但但但但但但但但是各大浏览器的新版本不再支持这个样式!!!!!!
现在各大主流浏览器对 overflow: overlay
的支持情况如下:
Chrome、Edge、Safari 和 Opera 之前有些版本还支持该属性,现在所有主流浏览器最近的版本全部不支持该属性。所以我们只能找其他方法解决
OverlayScrollbars
那么如何实现滚动条不挤占元素的位置呢? React 社区提供了 OverlayScrollbars 伪滚动条
OverlayScrollbars
是一个 JavaScript 滚动条插件,隐藏本机滚动条,提供自定义样式的覆盖滚动条并保持本机功能和感觉
它有下列优点
- 简单、强大且文档齐全的 API
- 高浏览器兼容性 - Firefox 59+、Chrome 55+、Opera 42+、Edge 15+和Safari 10+
- 完全可访问- 完全保留本机滚动行为
- 可以在服务器上运行(Node、Deno)Bun- SSR、SSG和ISR支持
- 在各种设备上进行测试 -移动设备、台式机和平板电脑
- 使用各种(和混合)输入进行测试 -鼠标、触摸和笔
- Treeshaking - 只捆绑你真正需要的东西
- 自动更新检测 -无轮询
- 使用最新的浏览器功能 -新浏览器中的最佳性能
- 双向 - LTR 或 RTL 方向支持
- 支持该body元素
- 支持所有虚拟滚动库
- 简单有效的滚动条样式
- 高度可定制
- TypeScript 支持 - 完全用 TypeScript 编写
- 无依赖 - 100% 自编写,确保小尺寸和最佳功能
- react、vue、angular和svelte的高质量和完全类型化的框架版本solid。
它支持在 React/Vue 等框架使用,下面以 React 例子说明其使用
在本地使用 Vite 起一个 React 测试项目
npm create vite@latest overlayscrollbars-starter -- --template react
然后在项目中引入 overlayscrollbars-react 依赖
npm i overlayscrollbars-react --save-dev
由于 overlayscrollbars-react 自己实现了滚动条的所有样式,所以需要在入口文件里引入样式文件
// main.jsx
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import "overlayscrollbars/overlayscrollbars.css";
const rootEl = document.getElementById("root");
ReactDOM.createRoot(rootEl).render(<App />);
文章开头的代码用 overlayscrollbars 改写如下
// App.jsx
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import "./App.css";
function App() {
return (
<>
<OverlayScrollbarsComponent className="wrapper" element={"div"}>
<p className="inner"></p>
</OverlayScrollbarsComponent>
</>
);
}
export default App;
最终效果如下图所示
使用 overlayscrollbars 后的滚动条不会挤占元素本来的宽度,缺丝毫不影响滚动,可以做出非常棒的用户体验
主要 API 使用
OverlayScrollbarsComponent 组件接受常规元素的所有属性,例如 div 和 span。此外它还具有自定义可选属性:
- element:传入代表根元素标签
- options:支持自定义 OverlayScrollbars
- events:接受传入 object 表示 OverlayScrollbars 支持的事件
- defer: 接受 boolean 或 object。表示在浏览器空闲的时候进行初始化,不阻塞主线程渲染
overlayscrollbars-react
推荐使用时加上 defer 属性,提升加载性能
接下来。我们重点看看 options 和 events 两个配置,这两个配置需要根据具体的业务进行自定义
先来看 options 这个配置项。options 接收 paddingAbsolute、showNativeOverlaidScrollbars、update、overflow 和 scrollbars 等配置项
paddingAbsolute
表示填充是否是绝对的showNativeOverlaidScrollbars
表示是否显示原生滚动条。 仅当本机滚动条被覆盖时才有效update
表示自定义自动更新行为overflow
表示自定义每个轴的溢出行为scrollbars
表示自定义滚动条的外观
events 支持 initialized
、updated
、destroyed
和 scroll
四个事件、其中 scroll 用的最多
总结
OverlayScrollbars 是一款非常优秀的伪滚动条工具,可以让滚动条在内容溢出时显示,但不会占据实际内容的空间,这样可以更好地保持布局的稳定性和一致性。