Appearance
OverlayScrollbars
一个 JavaScript 滚动条插件,可以隐藏原生滚动条,提供可自定义样式的覆盖滚动条,并保留原生功能和体验。
为什么?
我创建这个插件是因为我讨厌丑陋且占用空间的滚动条。类似的插件在功能、质量、简洁性、许可或浏览器支持方面都未能满足我的要求。
目标与功能
- 简单、强大且文档齐全的 API。
- 高浏览器兼容性 - Firefox 59+、Chrome 55+、Opera 42+、Edge 15+ 和 Safari 10+。
- 完全可访问 - 完全保留原生滚动行为。
- 可以在服务器上运行(
Node
、Deno
和Bun
)- 支持 SSR、SSG 和 ISR。 - 在各种设备上测试过 - 移动设备、桌面设备 和 平板设备。
- 测试过各种(和混合)输入 - 鼠标、触摸 和 笔。
- 树摇 - 仅打包你真正需要的部分。
- 自动更新检测 - 无需轮询。
- 利用最新的浏览器功能 - 在新浏览器中提供最佳性能。
- 流程独立 - 支持所有
direction
、flex-direction
和writing-mode
的值。 - 支持滚动捕捉。
- 支持所有 虚拟滚动 库。
- 支持
body
元素。 - 简单且有效的滚动条样式。
- 高度可定制。
- TypeScript 支持 - 完全用 TypeScript 编写。
- 无依赖 - 100% 自编写以确保小体积和最佳功能。
- 高质量且完全类型化的框架版本,适用于
react
、vue
、angular
、svelte
和solid
。
选择你的框架
除了原生 JavaScript 版本,你还可以使用官方框架组件和工具:
入门
npm 和 nodejs
OverlayScrollbars 可以从 npm 或你选择的包管理器下载:
sh
npm install overlayscrollbars
安装后,可以导入:
js
import "overlayscrollbars/overlayscrollbars.css";
import {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin,
} from "overlayscrollbars";
注意:如果路径
'overlayscrollbars/overlayscrollbars.css'
无法使用,请使用'overlayscrollbars/styles/overlayscrollbars.css'
作为 CSS 文件的导入路径。
您可以使用这个 Node 示例 作为参考或起点。
手动下载和嵌入
您可以在不使用任何打包工具或包管理器的情况下使用 OverlayScrollbars。
只需下载其中一个 发布版本 或使用 CDN。
- 使用带有
.browser
扩展名的 JavaScript 文件。 - 如果需要支持旧版浏览器,请使用带有
.es5
扩展名的 JavaScript 文件,否则使用.es6
文件。 - 对于生产环境,使用带有
.min
扩展名的 JavaScript / 样式表文件。
在您的 HTML 中手动嵌入 OverlayScrollbars:
html
<link type="text/css" href="path/to/overlayscrollbars.css" rel="stylesheet" />
<script
type="text/javascript"
src="path/to/overlayscrollbars.browser.es.js"
defer
></script>
使用全局变量 OverlayScrollbarsGlobal
来访问 API,类似于在 nodejs / 模块中使用:
js
var {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin,
} = OverlayScrollbarsGlobal;
您可以使用这个 浏览器示例 作为参考或起点。
本文档中的示例使用 import
语法,而不是 OverlayScrollbarsGlobal
对象。然而,两种版本是等价的。
初始化
OverlayScrollbars
的初始化是针对 每个元素 显式进行的。只有在插件初始化的元素上的滚动条会被更改。子元素的滚动条将保持不变,除非插件也在它们上面初始化。
您可以直接使用 Element
或 Object
初始化一个新实例,这样可以更好地控制初始化过程。
js
// 使用元素进行简单初始化
const osInstance = OverlayScrollbars(document.querySelector("#myElement"), {});
解决初始化闪烁问题
当你初始化 OverlayScrollbars 时,需要几毫秒的时间来创建并将所有元素附加到 DOM。在此期间,原生滚动条仍然可见,并将在初始化完成后被替换掉。这被视为闪烁。
要解决此行为,请将 data-overlayscrollbars-initialize
属性应用于目标元素(在为 body
元素初始化滚动条时,也应用于 html
元素)。
html
<!-- 针对 body 元素 -->
<html data-overlayscrollbars-initialize>
<head></head>
<body data-overlayscrollbars-initialize></body>
</html>
<!-- 针对所有其他元素 -->
<div data-overlayscrollbars-initialize>OverlayScrollbars 应用于此 div</div>
使用对象进行初始化
Details
这是一个深入的话题。点击这里阅读。
唯一必需的字段是 target
字段。这是插件将应用的字段。
如果你仅使用 target
字段进行对象初始化,结果等同于元素初始化:
js
// 两种初始化方式的结果相同
OverlayScrollbars(document.querySelector('#myElement'), {});
OverlayScrollbars({ target: document.querySelector('#myElement') }, {});
使用对象初始化时,你可以指定库如何处理生成的元素。 例如,你可以指定一个现有元素作为 viewport
元素。然后库将不会生成它,而是使用指定的元素:
js
OverlayScrollbars({
target: document.querySelector('#target'),
elements: {
viewport: document.querySelector('#viewport'),
},
}, {});
如果你有一个固定的 DOM 结构并且不希望 OverlayScrollbars 创建自己的元素,这非常有用。当你希望另一个库与 OverlayScrollbars 一起工作时,这种情况非常常见。
你还可以决定滚动条应该应用到哪个元素:
js
OverlayScrollbars(
{
target: document.querySelector("#target"),
scrollbars: {
slot: document.querySelector("#target").parentElement,
},
},
{}
);
最后但同样重要的是,您可以决定何时取消初始化:
js
OverlayScrollbars(
{
target: document.querySelector("#target"),
cancel: {
nativeScrollbarsOverlaid: true,
body: null,
},
},
{}
);
在上述示例中,如果原生滚动条被覆盖,或者如果您的目标是一个 body
元素且插件已确定初始化到 body
元素会干扰原生功能(如 window.scrollTo
),则初始化将被中止。
选项
您可以使用一组初始选项初始化 OverlayScrollbars,并可以随时通过 options
方法更改这些选项:
js
OverlayScrollbars(document.querySelector("#myElement"), {
overflow: {
x: "hidden",
},
});
深入了解选项
这是一个深入的话题。点击这里阅读。
默认选项为:
js
const defaultOptions = {
paddingAbsolute: false,
showNativeOverlaidScrollbars: false,
update: {
elementEvents: [["img", "load"]],
debounce: [0, 33],
attributes: null,
ignoreMutation: null,
},
overflow: {
x: "scroll",
y: "scroll",
},
scrollbars: {
theme: "os-theme-dark",
visibility: "auto",
autoHide: "never",
autoHideDelay: 1300,
autoHideSuspend: false,
dragScroll: true,
clickScroll: false,
pointers: ["mouse", "touch", "pen"],
},
};
paddingAbsolute
类型 | 默认值 |
---|---|
boolean | false |
指示内容的填充是否应为绝对值。
showNativeOverlaidScrollbars
类型 | 默认值 |
---|---|
boolean | false |
指示是否应显示原生覆盖的滚动条。
update.elementEvents
类型 | 默认值 |
---|---|
Array<[string, string]> | null | [['img', 'load']] |
一个元组数组。元组中的第一个值是一个 selector
,第二个值是 event names
。如果具有指定选择器的任何元素发出任何指定事件,插件将更新自身。默认值可以解释为“如果任何 img
元素发出 load
事件,插件将更新自身。”
update.debounce
类型 | 默认值 |
---|---|
[number, number] | number | null | [0, 33] |
注意:如果超时使用 0,将使用
requestAnimationFrame
而不是setTimeout
进行防抖。
对跟踪内容更改的 MutationObserver
进行防抖。如果传递 元组,第一个值是超时,第二个是最大等待时间。如果只有一个 数字,则被视为超时,没有最大等待时间。使用 null 则没有防抖。用于微调性能。
update.attributes
类型 | 默认值 |
---|---|
string[] | null | null |
注意:即使此选项为
null
,MutationObserver
也始终观察一组基本属性。
MutationObserver
应观察内容的其他属性数组。
update.ignoreMutation
类型 | 默认值 |
---|---|
((mutation) => any) | null | null |
一个函数,它接收一个 MutationRecord
作为参数。如果函数返回一个真值,则忽略该变异,插件不会更新。用于微调性能。
overflow.x
类型 | 默认值 |
---|---|
string | 'scroll' |
注意:有效值为:
'hidden'
、'scroll'
、'visible'
、'visible-hidden'
和'visible-scroll'
。
水平(x)轴的溢出行为。
overflow.y
类型 | 默认值 |
---|---|
string | 'scroll' |
注意:有效值为:
'hidden'
、'scroll'
、'visible'
、'visible-hidden'
和'visible-scroll'
。
垂直(y)轴的溢出行为。
scrollbars.theme
类型 | 默认值 |
---|---|
string | null | 'os-theme-dark' |
将指定的主题(类名)应用于滚动条。
scrollbars.visibility
类型 | 默认值 |
---|---|
string | 'auto' |
注意:有效值为:
'visible'
、'hidden'
和'auto'
。
如果滚动轴能够具有可滚动溢出,则滚动条的可见性。(轴的可滚动溢出仅在溢出行为设置为 'scroll'
或 'visible-scroll'
时可能。)
scrollbars.autoHide
类型 | 默认值 |
---|---|
string | 'never' |
注意:有效值为:
'never'
、'scroll'
、'leave'
和'move'
。
指示是否在某些用户操作后自动隐藏可见滚动条。
scrollbars.autoHideDelay
类型 | 默认值 |
---|---|
number | 1300 |
滚动条自动隐藏前的延迟时间(毫秒)。
scrollbars.autoHideSuspend
类型 | 默认值 |
---|---|
boolean | false |
暂停 autoHide 功能,直到执行第一次滚动交互。
此选项的默认值为 false
,以保持向后兼容性,但建议设置为 true
以提高可访问性。
scrollbars.dragScroll
类型 | 默认值 |
---|---|
boolean | true |
指示是否可以拖动滚动条手柄进行滚动。
scrollbars.clickScroll
类型 | 默认值 |
---|---|
boolean | 'instant' | false |
注意:如果设置为
true
,则需要 ClickScrollPlugin。
指示是否可以点击滚动条轨道进行滚动。
scrollbars.pointers
类型 | 默认值 |
---|---|
string[] | null | ['mouse', 'touch', 'pen'] |
插件应响应的 PointerTypes
。
TypeScript
ts
// OverlayScrollbars 实例的选项。
type Options = {
// 填充是否应为绝对值。
paddingAbsolute: boolean;
// 是否显示原生滚动条。仅在原生滚动条被覆盖时有效。
showNativeOverlaidScrollbars: boolean;
// 自定义自动更新行为。
update: {
/**
* 来自具有给定选择器的元素的给定事件将触发更新。
* 对于 MutationObserver 和 ResizeObserver 无法检测到的内容非常有用
* 例如:图像的 `load` 事件或 `transitionend` / `animationend` 事件。
*/
elementEvents: Array<[elementSelector: string, eventNames: string]> | null;
/**
* 用于检测内容更改的防抖。
* 如果提供了元组,您可以自定义 `timeout` 和 `maxWait`(以毫秒为单位)。
* 如果是单个数字,则仅自定义 `timeout`。
*
* 如果 `timeout` 为 `0`,仍然存在防抖(通过 `requestAnimationFrame` 而不是 `setTimeout` 完成)。
*/
debounce: [timeout: number, maxWait: number] | number | null;
/**
* 如果更改了 HTML 属性,将触发更新。
* 基本属性如 `id`、`class`、`style` 等始终被观察,不必显式添加。
*/
attributes: string[] | null;
// 一个函数,使得可以忽略内容变异或为 null 如果不应忽略任何内容。
ignoreMutation: ((mutation: MutationRecord) => any) | null;
};
// 自定义每个轴的溢出行为。
overflow: {
// 水平(x)轴的溢出行为。
x: OverflowBehavior;
// 垂直(y)轴的溢出行为。
y: OverflowBehavior;
};
// 自定义滚动条的外观。
scrollbars: {
// 滚动条的主题。主题值将作为 `class` 添加到实例的所有 `scrollbar` 元素。
theme: string | null;
// 滚动条的可见性行为。
visibility: ScrollbarsVisibilityBehavior;
// 滚动条的自动隐藏行为。
autoHide: ScrollbarsAutoHideBehavior;
// 滚动条的自动隐藏延迟(以毫秒为单位)。
autoHideDelay: number;
// 滚动条的自动隐藏行为是否暂停,直到发生滚动。
autoHideSuspend: boolean;
// 是否可以拖动滚动条的手柄以滚动视口。
dragScroll: boolean;
// 是否可以点击滚动条的轨道以滚动视口。
clickScroll: ScrollbarsClickScrollBehavior;
// 支持的指针类型数组。
pointers: string[] | null;
};
};
markdown
// 轴的溢出行为。
type OverflowBehavior =
// 无法滚动,内容被裁剪。
| 'hidden'
// 无法滚动,内容不被裁剪。
| 'visible'
// 如果有溢出,可以滚动。
| 'scroll'
/\*\*
- 如果另一个轴没有溢出,行为类似于 `visible`。
- 如果另一个轴有溢出,行为类似于 `hidden`。
\*/
| 'visible-hidden'
/\*\*
- 如果另一个轴没有溢出,行为类似于 `visible`。
- 如果另一个轴有溢出,行为类似于 `scroll`。
\*/
| 'visible-scroll';
// 滚动条的可见性行为。
type ScrollbarsVisibilityBehavior =
// 滚动条始终可见。
| 'visible'
// 滚动条始终隐藏。
| 'hidden'
// 只有在有溢出时滚动条才可见。
| 'auto';
// 滚动条自动隐藏行为
type ScrollbarsAutoHideBehavior =
// 滚动条从不自动隐藏。
| 'never'
// 除非用户滚动,否则滚动条隐藏。
| 'scroll'
// 除非指针在主机元素中移动或用户滚动,否则滚动条隐藏。
| 'move'
// 如果指针离开主机元素或除非用户滚动,否则滚动条隐藏。
| 'leave';
// 滚动条点击滚动行为。
type ScrollbarsClickScrollBehavior = boolean | 'instant';
事件
您可以使用一组初始事件初始化 OverlayScrollbars,可以随时通过 on
和 off
方法进行管理:
js
OverlayScrollbars(
document.querySelector("#myElement"),
{},
{
updated(osInstance, onUpdatedArgs) {
// ...
},
}
);
深入了解事件
这是一个深入的话题。点击这里阅读。
注意:每个事件都会接收从中调度的
instance
作为第一个参数。始终如此。
initialized
参数 | 描述 |
---|---|
instance | 调度事件的实例。 |
在所有生成的元素、观察者和事件被附加到 DOM 后调度。
updated
参数 | 描述 |
---|---|
instance | 调度事件的实例。 |
onUpdatedArgs | 一个详细描述更新的 object 。 |
注意:如果触发了更新但没有任何变化,则不会调度事件。
在实例更新后调度。
destroyed
参数 | 描述 |
---|---|
instance | 调度事件的实例。 |
canceled | 一个 boolean ,指示初始化是否被取消并因此被销毁。 |
在所有生成的元素、观察者和事件从 DOM 中移除后调度。
scroll
参数 | 描述 |
---|---|
instance | 调度事件的实例。 |
event | DOM 事件的原始 event 参数。 |
通过滚动视口调度。
TypeScript
ts
// 事件名称与其监听器参数之间的映射。
type EventListenerArgs = {
// 在所有元素初始化并附加后调度。
initialized: [instance: OverlayScrollbars];
// 在更新后调度。
updated: [
instance: OverlayScrollbars,
onUpdatedArgs: OnUpdatedEventListenerArgs
];
// 在所有元素、观察者和事件被销毁后调度。
destroyed: [instance: OverlayScrollbars, canceled: boolean];
// 在滚动时调度。
scroll: [instance: OverlayScrollbars, event: Event];
};
markdown
interface OnUpdatedEventListenerArgs {
// 描述 DOM 中更改内容的提示。
updateHints: {
// 主机元素的大小是否发生了变化。
sizeChanged: boolean;
// 主机元素的方向是否发生了变化。
directionChanged: boolean;
// 内在高度行为是否发生了变化。
heightIntrinsicChanged: boolean;
// 视口元素的溢出边缘(clientWidth / clientHeight)是否发生了变化。
overflowEdgeChanged: boolean;
// 溢出量是否发生了变化。
overflowAmountChanged: boolean;
// 溢出样式是否发生了变化。
overflowStyleChanged: boolean;
// 滚动坐标是否发生了变化。
scrollCoordinatesChanged: boolean;
// 是否发生了主机突变。
hostMutation: boolean;
// 是否发生了内容突变。
contentMutation: boolean;
};
// 更改的选项。
changedOptions: PartialOptions;
// 更新是否在强制无效缓存的情况下发生。
force: boolean;
}
实例
可以通过调用 OverlayScrollbars
函数并传入一个元素和选项对象来创建 OverlayScrollbars 实例。
js
const osInstance = OverlayScrollbars(document.body, {});
实例方法
这是一个深入的话题。点击这里阅读。
options(): Options
获取实例的当前选项。
返回值 | 描述 |
---|---|
Options | 当前选项。 |
options(newOptions, pure?): Options
设置实例的当前选项。
参数 | 类型 | 描述 |
---|---|---|
newOptions | PartialOptions | 应用的新(部分)选项。 |
pure | boolean | undefined | 在添加新选项之前是否重置选项。 |
返回值 | 描述 |
---|---|
Options | 完整的新选项。 |
on(eventListeners, pure?): Function
向实例添加事件监听器。
参数 | 类型 | 描述 |
---|---|---|
eventListeners | EventListeners | 包含添加的监听器的对象。字段是事件名称和监听器。 |
pure | boolean | undefined | 在添加新监听器之前是否移除所有已添加的事件监听器。 |
返回值 | 描述 |
---|---|
Function | 移除所有添加的事件监听器的函数。 |
on(name, listener): Function
向实例添加单个事件监听器。
参数 | 类型 | 描述 |
---|---|---|
name | string | 事件名称。 |
listener | Function | 事件分派时调用的函数。 |
返回值 | 描述 |
---|---|
Function | 移除添加的事件监听器的函数。 |
on(name, listeners): Function
向实例添加多个事件监听器。
参数 | 类型 | 描述 |
---|---|---|
name | string | 事件名称。 |
listeners | Function[] | 事件分派时调用的函数。 |
返回值 | 描述 |
---|---|
Function | 移除添加的事件监听器的函数。 |
off(name, listener): void
从实例中移除单个事件监听器。
参数 | 类型 | 描述 |
---|---|---|
name | string | 事件名称。 |
listener | Function | 要移除的函数。 |
off(name, listeners): void
从实例中移除多个事件监听器。
参数 | 类型 | 描述 |
---|---|---|
name | string | 事件名称。 |
listeners | Function[] | 要移除的函数。 |
update(force?): boolean
更新实例。
参数 | 类型 | 描述 |
---|---|---|
force | boolean | undefined | 是否强制使缓存无效。 |
返回值 | 描述 |
---|---|
Function | 一个布尔值,指示是否通过此更新触发了 update 事件。 |
state(): State
获取实例的状态。
返回值 | 描述 |
---|---|
State | 描述实例状态的对象。 |
elements(): Elements
获取实例的元素。
返回值 | 描述 |
---|---|
Elements | 描述实例元素的对象。 |
destroy(): void
销毁实例并移除所有添加的元素。
plugin(plugin: object): object | undefined
获取传入插件的实例模块实例。
返回值 | 描述 |
---|---|
object | undefined | 描述插件实例模块实例的对象,如果未找到实例则为 undefined 。 |
TypeScript
ts
// OverlayScrollbars TypeScript 接口的简化版本。
interface OverlayScrollbars {
// 获取实例的当前选项。
options(): Options;
// 设置实例的当前选项。
options(newOptions: PartialOptions, pure?: boolean): Options;
// 向实例添加事件监听器。
on(eventListeners: EventListeners, pure?: boolean): () => void;
// 向实例添加单个事件监听器。
on<N extends keyof EventListenerArgs>(
name: N,
listener: EventListener<N>
): () => void;
// 向实例添加多个事件监听器。
on<N extends keyof EventListenerArgs>(
name: N,
listener: EventListener<N>[]
): () => void;
// 从实例中移除单个事件监听器。
off<N extends keyof EventListenerArgs>(
name: N,
listener: EventListener<N>
): void;
// 从实例中移除多个事件监听器。
off<N extends keyof EventListenerArgs>(
name: N,
listener: EventListener<N>[]
): void;
// 更新实例。
update(force?: boolean): boolean;
// 获取实例的状态。
state(): State;
// 获取实例的元素。
elements(): Elements;
// 销毁实例并移除所有添加的元素。
destroy(): void;
// 获取传入插件的实例模块实例。
plugin<P extends InstancePlugin>(
osPlugin: P
): InferInstancePluginModuleInstance<P> | undefined;
}
// 描述 OverlayScrollbars 实例的状态。
interface State {
// 描述当前的像素填充。
padding: TRBL;
// 当前填充是否为绝对值。
paddingAbsolute: boolean;
// 视口的客户端宽度(x)和高度(y),以像素为单位。
overflowEdge: XY<number>;
// 溢出量,以像素为单位。
overflowAmount: XY<number>;
// 视口的 CSS 溢出样式。
overflowStyle: XY<OverflowStyle>;
// 视口是否有溢出。
hasOverflow: XY<boolean>;
// 视口的滚动坐标。
scrollCoordinates: {
// 每个轴的起始(原点)滚动坐标。
start: XY<number>;
// 每个轴的结束滚动坐标。
end: XY<number>;
};
// 方向是否被认为是 rtl。
directionRTL: boolean;
// 实例是否被认为已销毁。
destroyed: boolean;
}
// 描述 OverlayScrollbars 实例的元素。
interface Elements {
// 应用实例的元素。
target: HTMLElement;
// 主机元素。它是所有其他元素的根。
host: HTMLElement;
/**
* 负责正确填充的元素。
* 根据初始化,它可以与视口元素相同。
*/
padding: HTMLElement;
// 负责滚动的元素。
viewport: HTMLElement;
/**
* 负责保存实际内容的元素。
* 根据初始化,它可以与视口元素相同。
*/
content: HTMLElement;
/**
* 可以通过它获取当前 `scrollLeft` 或 `scrollTop` 偏移量的元素。
* 根据目标元素,它可以与视口元素相同。
*/
scrollOffsetElement: HTMLElement;
/**
* 可以通过它添加 `scroll` 事件的元素。
* 根据目标元素,它可以与视口元素相同。
*/
scrollEventElement: HTMLElement | Document;
// 水平滚动条的元素。
scrollbarHorizontal: CloneableScrollbarElements;
// 垂直滚动条的元素。
scrollbarVertical: CloneableScrollbarElements;
}
静态对象
静态 OverlayScrollbars
对象。
js
OverlayScrollbars.plugin(SomePlugin);
静态对象方法
这是一个深入的话题。点击这里阅读。
valid(osInstance): boolean
检查传入的值是否为有效且未销毁的 overlayscrollbars 实例
参数 | 类型 | 描述 |
---|---|---|
osInstance | any | 要检查的值。 |
返回值 | 描述 |
---|---|
boolean | 传入的值是否为有效且未销毁的 overlayscrollbars 实例。 |
env(): Environment
获取环境。
返回值 | 描述 |
---|---|
Environment | 描述环境的对象。 |
nonce(newNonce): void
为内联样式设置 nonce 属性。
参数 | 类型 | 描述 |
---|---|---|
newNonce | string | undefined | 内联样式的 nonce 属性。 |
plugin(plugin): object | undefined
添加单个插件。
参数 | 类型 | 描述 |
---|---|---|
plugin | object | 要添加的插件。 |
返回值 | 描述 |
---|---|
object | void | 描述插件静态模块实例的对象,如果未找到实例则为 void 。 |
plugin(plugins): (object | void)[]
添加多个插件。
参数 | 类型 | 描述 |
---|---|---|
plugins | object[] | 要添加的插件。 |
返回值 | 描述 |
---|---|
(object | void)[] | 描述插件静态模块实例的数组,如果未找到实例则为 undefined 。 |
TypeScript
ts
// OverlayScrollbars 静态对象。
interface OverlayScrollbarsStatic {
// 获取传入目标的实例或 `undefined` 如果目标没有实例。
(target: InitializationTarget): OverlayScrollbars | undefined;
// 使用传入的选项和事件监听器初始化传入目标的 OverlayScrollbars。
(
target: InitializationTarget,
options: PartialOptions,
eventListeners?: EventListeners
): OverlayScrollbars;
// 检查传入的值是否为有效且未销毁的 overlayscrollbars 实例。
valid(osInstance: any): osInstance is OverlayScrollbars;
// 获取环境。
env(): Environment;
// 为内联样式设置 nonce 属性。
nonce(newNonce: string | undefined): void;
// 添加单个插件。
plugin(plugin: Plugin): InferStaticPluginModuleInstance<Plugin>;
// 添加多个插件。
plugin(plugins: Plugin[]): InferStaticPluginModuleInstance<Plugin>[];
}
// 描述 OverlayScrollbars 环境。
interface Environment {
// 浏览器/系统的原生滚动条大小。
scrollbarsSize: XY<number>;
// 原生滚动条是否被覆盖。
scrollbarsOverlaid: XY<boolean>;
// 浏览器是否支持原生滚动条隐藏。
scrollbarsHiding: boolean;
// 浏览器是否支持 ScrollTimeline API。
scrollTimeline: boolean;
// 如果没有其他指定,则使用的默认初始化。
staticDefaultInitialization: Initialization;
// 如果没有其他指定,则使用的默认选项。
staticDefaultOptions: Options;
// 返回当前默认初始化。
getDefaultInitialization(): Initialization;
// 返回当前默认选项。
getDefaultOptions(): Options;
/**
* 设置新的默认初始化。
* 如果新的默认初始化部分填充,则与当前默认初始化深度合并。
* @param newDefaultInitialization 新的默认初始化。
* @returns 当前默认初始化。
*/
setDefaultInitialization(
newDefaultInitialization: PartialInitialization
): Initialization;
/**
* 设置新的默认选项。
* 如果新的默认选项部分填充,则与当前默认选项深度合并。
* @param newDefaultOptions 新的默认选项。
* @returns 当前默认选项。
*/
setDefaultOptions(newDefaultOptions: PartialOptions): Options;
}
样式
OverlayScrollbars 提供了两个主题,分别是 os-theme-dark
和 os-theme-light
。您可以使用 scrollbars.theme
选项来更改主题。
自定义主题可以通过多种方式完成。最简单和最快的方法是使用预定义的 CSS 自定义属性
,也称为 CSS 变量。如果这还不够,您可以添加自定义类名或为现有类名添加自定义样式。
深入样式
这是一个深入的话题。点击这里阅读。
CSS 自定义属性
OverlayScrollbars 提供了一组 CSS 自定义属性
,使滚动条样式变得简单快捷:
scss
.os-scrollbar {
// 滚动条的大小
--os-size: 0;
// 滚动条的轴垂直填充(水平:padding-y,垂直:padding-x)
--os-padding-perpendicular: 0;
// 滚动条的轴填充(水平:padding-x,垂直:padding-y)
--os-padding-axis: 0;
// 滚动条轨道的边框半径
--os-track-border-radius: 0;
// 滚动条轨道的背景
--os-track-bg: none;
// 滚动条轨道的 :hover 背景
--os-track-bg-hover: none;
// 滚动条轨道的 :active 背景
--os-track-bg-active: none;
// 滚动条轨道的边框
--os-track-border: none;
// 滚动条轨道的 :hover 边框
--os-track-border-hover: none;
// 滚动条轨道的 :active 边框
--os-track-border-active: none;
// 滚动条手柄的边框半径
--os-handle-border-radius: 0;
// 滚动条手柄的背景
--os-handle-bg: none;
// 滚动条手柄的 :hover 背景
--os-handle-bg-hover: none;
// 滚动条手柄的 :active 背景
--os-handle-bg-active: none;
// 滚动条手柄的边框
--os-handle-border: none;
// 滚动条手柄的 :hover 边框
--os-handle-border-hover: none;
// 滚动条手柄的 :active 边框
--os-handle-border-active: none;
// 滚动条手柄的最小大小
--os-handle-min-size: 33px;
// 滚动条手柄的最大大小
--os-handle-max-size: none;
// 滚动条手柄的轴垂直大小(水平:高度,垂直:宽度)
--os-handle-perpendicular-size: 100%;
// 滚动条手柄的 :hover 轴垂直大小(水平:高度,垂直:宽度)
--os-handle-perpendicular-size-hover: 100%;
// 滚动条手柄的 :active 轴垂直大小(水平:高度,垂直:宽度)
--os-handle-perpendicular-size-active: 100%;
// 增加滚动条手柄的交互区域。
--os-handle-interactive-area-offset: 0;
}
您可以同时更改两个滚动条的属性,也可以为每个滚动条轴更改属性。在下面的示例中,我选择了 os-theme-custom
作为主题名称:
scss
// 水平和垂直滚动条为 10px
.os-theme-custom {
--os-size: 10px;
}
// 水平滚动条为 10px
.os-theme-custom.os-scrollbar-horizontal {
--os-size: 10px;
}
// 垂直滚动条为 20px
.os-theme-custom.os-scrollbar-vertical {
--os-size: 20px;
}
然后,您可以通过 scrollbars.theme
选项分配您的主题:
js
OverlayScrollbars(document.body, {
scrollbars: {
theme: "os-theme-custom",
},
});
由于滚动条样式通常很简单,这组选项应该足以获得您想要的样式。 如果您需要更多的自由,您可以通过向下节中描述的基本类名添加样式来创建自己的样式。
滚动条结构和 CSS 类名
滚动条的 HTML 标记如下所示:
html
<div class="os-scrollbar os-scrollbar-horizontal">
<div class="os-scrollbar-track">
<div class="os-scrollbar-handle"></div>
</div>
</div>
<div class="os-scrollbar os-scrollbar-vertical">
<div class="os-scrollbar-track">
<div class="os-scrollbar-handle"></div>
</div>
</div>
类名是简化的,在实际应用中,.os-scrollbar
元素可以有其他类名来修改外观(主要是可见性和对齐)。
下面是您将遇到的最重要类名的列表:
CSS 类名 | 描述 |
---|---|
.os-scrollbar | 滚动条的根元素。 |
.os-scrollbar-rtl | 指示滚动条所属的主机元素的 RTL 方向。 |
.os-scrollbar-horizontal | 水平滚动条的根元素。 |
.os-scrollbar-vertical | 垂直滚动条的根元素。 |
.os-scrollbar-handle-interactive | 指示滚动条内的手柄是交互式的(scrollbars.dragScroll 不是 false )。 |
.os-scrollbar-track-interactive | 指示滚动条内的轨道是交互式的(scrollbars.clickScroll 不是 false )。 |
.os-scrollbar-track | 轨道元素。这是嵌套手柄元素的轨道。如果 scrollbars.clickScroll 不是 false ,这是用户可以点击以更改滚动偏移量的元素。 |
.os-scrollbar-handle | 手柄元素。如果 scrollbars.dragScroll 不是 false ,这是用户可以拖动以更改滚动偏移量的手柄。 |
如果您创建自己的主题,请仅使用上面列出的类。所有其他类都是用于更改滚动条的可见性、对齐和指针事件的修饰类。
注意事项
您 CSS 文件中选择的主题类名必须与选项中分配的主题名称匹配。如果 CSS 类名是 .my-theme
,则 scrollbars.theme
必须是 'my-theme'
。
请注意您的堆栈。例如,css-modules
会更改您的类名以避免命名冲突。始终检查您的 CSS 是否符合预期。
插件
任何不被视为核心功能或旧浏览器兼容性的内容都通过插件公开。这是因为所有未使用的插件在树形抖动期间都会被省略,不会出现在您的最终包中。OverlayScrollbars 附带以下插件:
- ScrollbarsHidingPlugin:需要用于不支持原生滚动条样式的旧浏览器。您可以在此处找到需要此插件的浏览器列表(请注意,即使
iOS Safari >= 14
被标记为不支持,您只需要此插件用于iOS < 7.1
)。 - SizeObserverPlugin:需要用于不支持
ResizeObserver
API 的旧浏览器。您可以在此处找到需要此插件的浏览器列表 - ClickScrollPlugin:如果您想使用选项
scrollbars: { clickScroll: true }
。
使用插件
插件的使用方式如下:
ts
import {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin,
} from "overlayscrollbars";
markdown
// 单个插件
OverlayScrollbars.plugin(ScrollbarsHidingPlugin);
// 多个插件
OverlayScrollbars.plugin([SizeObserverPlugin, ClickScrollPlugin]);
深入了解插件
这是一个深入的话题。点击这里阅读。
插件是具有单个字段的普通对象,字段的名称就是插件的名称。这个名称是插件的标识符,必须在所有插件中唯一。如果多个插件具有相同的名称,最后添加的插件会覆盖之前添加的同名插件。
插件模块
插件模块是插件模块实例的构造函数。插件模块有两种类型:static
和 instance
。单个插件必须有一个或多个模块。插件模块可以返回一个实例,但不是必须的。
静态插件模块
static
插件模块在插件通过 OverlayScrollbars.plugin
函数添加时被调用。
带有 static
模块的插件示例:
js
const staticPlugin = {
// 插件名称为 `examplePlugin`。
examplePlugin: {
// `static` 函数描述一个静态模块并返回模块实例,如果不需要实例则返回 void / undefined。
// `osStatic` 参数是全局的 `OverlayScrollbars` 对象。
static: (osStatic) => {
let count = 0;
const staticPluginModuleInstance = {
getCount: () => count,
increment: () => {
count++;
},
};
return staticPluginModuleInstance;
},
},
};
当插件通过 OverlayScrollbars.plugin
函数添加时,静态模块实例被返回:
js
const staticModuleInstance = OverlayScrollbars.plugin(staticPlugin); // 插件的静态模块被调用
staticModuleInstance.count; // 0
staticModuleInstance.increment();
staticModuleInstance.count; // 1
实例插件模块
instance
插件模块在创建新的 OverlayScrollbars
实例时被调用,但在 initialized
事件被分派之前。
带有 instance
模块的插件示例:
js
const instancePlugin = {
// 插件名称为 `examplePlugin`。
examplePlugin: {
// 实例函数描述一个实例模块并返回模块实例,如果不需要实例则返回 void / undefined。
// `osInstance` 参数是插件绑定的 OverlayScrollbar 实例。
// `event` 参数是一个函数,用于向实例添加无法从插件外部移除的事件。
// `osStatic` 参数是全局的 OverlayScrollbar 对象。
instance: (osInstance, event, osStatic) => {
let count = 0;
js
const instancePluginModuleInstance = {
getCount: () => count,
increment: () => { count++ },
}
// 当实例被初始化时触发的事件。
event('initialized', () => {
console.log("instance initialized");
});
// 当视口滚动时触发的事件。
const removeScrollEvent = event('scroll', () => {
console.log("viewport scrolled");
removeScrollEvent(); // 在第一次滚动后移除事件。
});
return instancePluginModuleInstance;
}
}
}
当插件通过 OverlayScrollbars.plugin
函数添加时,从那时起所有的 OverlayScrollbar 实例将自动添加该插件。之前创建的实例将不会有该插件。实例模块实例通过 osInstance.plugin
函数返回:
js
OverlayScrollbars.plugin(instancePlugin); // 插件已添加
const osInstance = OverlayScrollbars(document.body, {}); // 插件的实例模块被调用
const instancePluginInstance = osInstance.plugin(instancePlugin);
instancePluginInstance.count; // 0
instancePluginInstance.increment();
instancePluginInstance.count; // 1
TypeScript
ts
// 描述一个 OverlayScrollbar 插件。
type Plugin<
// 插件的名称。
Name extends string = string,
// 静态模块的模块实例类型。
S extends PluginModuleInstance | void = PluginModuleInstance | void,
// 实例模块的模块实例类型。
I extends PluginModuleInstance | void = PluginModuleInstance | void
> = {
[pluginName in Name]: PluginModule<S, I>;
};
// 描述一个只有静态模块的 OverlayScrollbar 插件。
type StaticPlugin<
Name extends string = string,
T extends PluginModuleInstance = PluginModuleInstance
> = Plugin<Name, T, void>;
// 描述一个只有实例模块的 OverlayScrollbar 插件。
type InstancePlugin<
Name extends string = string,
T extends PluginModuleInstance = PluginModuleInstance
> = Plugin<Name, void, T>;
typescript
// 推断传递的插件的静态模块实例的类型。
type InferStaticPluginModuleInstance<T extends StaticPlugin>;
// 推断传递的插件的实例模块实例的类型。
type InferInstancePluginModuleInstance<T extends InstancePlugin>;
常见问题
如何获取/设置
应用了 OverlayScrollbars 的元素的滚动位置
?
如果你将 OverlayScrollbars
应用于 body
元素,你可以使用 window.scrollX
、window.scrollY
、window.scroll
、window.scrollTo
、window.scrollBy
或任何其他原生 API。
如果插件应用于其他元素,你需要首先使用 instance.elements()
函数获取 viewport
元素。对于这个元素,你可以使用 element.scrollTop
、element.scrollLeft
、element.scroll
、element.scrollTo
、element.scrollBy
或任何其他原生 API。
js
const { viewport } = osInstance.elements();
const { scrollLeft, scrollTop } = viewport; // 获取滚动偏移
viewport.scrollTo({ top: 0 }); // 设置滚动偏移
是否可以限制/调整滚动条手柄长度
?
你可以通过设置 min-width / min-height
和 max-width / max-height
样式来调整滚动条的手柄长度:
css
/* 水平边界 */
.os-scrollbar-horizontal .os-scrollbar-handle {
min-width: 50px;
max-width: 200px;
}
/* 垂直边界 */
.os-scrollbar-vertical .os-scrollbar-handle {
min-height: 40px;
max-height: 40px;
}
你可以为两个属性分配相同的值,以强制滚动条始终保持相同的大小。
设置 width
和 height
属性无效,因为这些属性由插件自动设置。
与 v1
的功能比较
- 缺少
scroll
功能。计划作为plugin
提供。(进行中) - 尚不支持对
textarea
元素的初始化。计划作为plugin
提供。(进行中)
未来计划
- 提供基于插件的支持以弥补缺失的功能。(可树摇)
- 在错误修复和增强方面进行频繁更新。(始终使用最新的浏览器功能)
- 改进测试。(单元测试和浏览器测试)
使用者
许可证
MIT