OverlayScrollbars Logo

OverlayScrollbars
中文文档

一个 JavaScript 滚动条插件,隐藏原生滚动条,提供可自定义样式的叠加滚动条,并保留原生功能和手感。

被谁使用
SpotifyIntelliJ IDEAStorybookAdmin LTEScramble.cloud
OverlayScrollbars on Github

寻找 v1 版本文档? 点击这里

DownloadsVersionLicenseCode CoverageMax. Bundle Size

为什么?

我创建这个插件是因为我讨厌又丑又占空间的滚动条。其他类似的插件在功能、质量、简洁性、许可协议或浏览器支持方面都无法满足我的需求。

目标与功能

选择你的框架

除了原生 JavaScript 版本外,你还可以使用官方提供的框架组件和工具:

ReactVueAngularSvelteSolid

快速入门

npm 和 nodejs

OverlayScrollbars 可以通过 npm 或者你选择的包管理工具下载:

npm install overlayscrollbars

安装完成后,可以导入它:

import 'overlayscrollbars/overlayscrollbars.css'; import { OverlayScrollbars, ScrollbarsHidingPlugin, SizeObserverPlugin, ClickScrollPlugin } from 'overlayscrollbars';

注意:如果路径 'overlayscrollbars/overlayscrollbars.css' 无法正常工作,请使用 'overlayscrollbars/styles/overlayscrollbars.css' 作为 CSS 文件的导入路径。

你可以参考并使用这个 Node 示例 作为起点。

手动下载与嵌入

你可以在没有任何打包工具或包管理器的情况下使用 OverlayScrollbars。
只需从 Releases 下载一个版本,或使用 CDN

在 HTML 中手动嵌入 OverlayScrollbars:

<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,就像在 Node.js 或模块中一样:

var { OverlayScrollbars, ScrollbarsHidingPlugin, SizeObserverPlugin, ClickScrollPlugin } = OverlayScrollbarsGlobal;

你可以参考这个 浏览器示例 作为参考或起点。

本文档中的示例使用了 import 语法,而不是 OverlayScrollbarsGlobal 对象,但这两种方式是等效的。

初始化

OverlayScrollbars 的初始化是针对每个元素进行的 显式 操作。只有在插件初始化的元素上,滚动条才会被修改。子元素的滚动条将保持不变,除非插件也在这些子元素上初始化。

你可以直接通过 ElementObject 初始化一个新实例,使用 Object 可以让你更精细地控制初始化过程。

// 使用元素进行简单初始化 const osInstance = OverlayScrollbars(document.querySelector('#myElement'), {});

避免初始化闪烁

当你初始化 OverlayScrollbars 时,它需要几毫秒来创建并将所有元素添加到 DOM 中。在此过程中,原生滚动条仍然可见,直到初始化完成并切换为 OverlayScrollbars。这会表现为闪烁现象。

为了解决这个问题,可以在目标元素上添加 data-overlayscrollbars-initialize 属性(如果初始化的是 body 元素,还需要在 html 元素上添加该属性)。

<!-- 对于 body 元素 --> <html data-overlayscrollbars-initialize> <head></head> <body data-overlayscrollbars-initialize></body> </html> <!-- 对于其他元素 --> <div data-overlayscrollbars-initialize> OverlayScrollbars 已应用于这个 div </div>

使用对象初始化

这是一个深入的主题。点击这里阅读更多。


唯一必需的字段是 target 字段。这个字段指定了插件应用的目标元素。如果你仅使用 target 字段进行对象初始化,结果与元素初始化是等效的:

// 两种初始化方式的结果是一样的 OverlayScrollbars(document.querySelector('#myElement'), {}); OverlayScrollbars({ target: document.querySelector('#myElement') }, {});

当使用对象初始化时,你可以指定库如何处理生成的元素。例如,你可以指定一个现有元素作为 viewport 元素。这样,库就不会生成该元素,而是使用指定的元素:

OverlayScrollbars({ target: document.querySelector('#target'), elements: { viewport: document.querySelector('#viewport'), }, }, {});

这在你有固定的 DOM 结构并且不希望 OverlayScrollbars 创建自己的元素时非常有用。此类情况通常发生在你希望其他库与 OverlayScrollbars 一起工作时。


你还可以决定将滚动条应用于哪个元素:

OverlayScrollbars({ target: document.querySelector('#target'), scrollbars: { slot: document.querySelector('#target').parentElement, }, }, {});

最后,你还可以决定何时取消初始化:

OverlayScrollbars({ target: document.querySelector('#target'), cancel: { nativeScrollbarsOverlaid: true, body: null, } }, {});

在上述示例中,如果原生滚动条已经叠加,或者目标元素是 body 元素并且插件已确定初始化 body 元素会干扰原生功能(如 window.scrollTo),则初始化将被中止。

配置选项

你可以在初始化时为 OverlayScrollbars 设置一组初始配置选项,并且可以随时通过 options 方法进行更改:

OverlayScrollbars(document.querySelector('#myElement'), { overflow: { x: 'hidden', }, });

配置选项详解

这是一个深入的主题。点击这里阅读更多。


默认的配置选项是:

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

类型默认值
booleanfalse

指示内容的内边距是否应该是绝对定位的。

showNativeOverlaidScrollbars

类型默认值
booleanfalse

指示是否显示原生的叠加滚动条。


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[] | nullnull

注意:即使此选项为 nullMutationObserver 也会始终观察一组基础属性。

这是一个额外的属性数组,MutationObserver 将会观察这些属性的变化。

update.ignoreMutation

类型默认值
((mutation) => any) | nullnull

这是一个接收 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

类型默认值
number1300

滚动条在自动隐藏之前的延迟时间(以毫秒为单位)。

scrollbars.autoHideSuspend

类型默认值
booleanfalse

暂停自动隐藏功能,直到第一次滚动交互发生。
此选项的默认值为 false,为了向后兼容,但为了更好的可访问性,建议将其设置为 true

scrollbars.dragScroll

类型默认值
booleantrue

指示是否可以拖动滚动条滑块进行滚动。

scrollbars.clickScroll

类型默认值
boolean | 'instant'false

注意:如果设置为 true,则需要 ClickScrollPlugin 插件。

指示是否可以点击滚动条轨道进行滚动。

scrollbars.pointers

类型默认值
string[] | null['mouse', 'touch', 'pen']

插件应响应的 PointerTypes

TypeScript

// 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; }; }; // 轴的溢出行为。 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 时设置初始的事件,这些事件可以通过 onoff 方法随时进行管理:

OverlayScrollbars(document.querySelector('#myElement'), {}, { updated(osInstance, onUpdatedArgs) { // 事件处理逻辑... } });

事件深入解析

这是一个深入的主题。点击此处阅读。


注意:每个事件都会将触发事件的 instance 作为第一个参数传递。始终如此。

initialized

参数描述
instance触发事件的实例

在所有生成的元素(elements)、观察者(observers)和事件(events)被添加到 DOM 后触发。

updated

参数描述
instance触发事件的实例
onUpdatedArgs一个 object,详细描述更新内容

注意:如果更新被触发但没有任何变化,则该事件不会被触发。

在实例更新后触发。

destroyed

参数描述
instance触发事件的实例
canceled一个 boolean,指示初始化是否被取消,因此实例被销毁

在所有生成的元素(elements)、观察者(observers)和事件(events)被从 DOM 中移除后触发。

scroll

参数描述
instance触发事件的实例
eventDOM 事件的原始 event 参数

通过滚动视口时触发。

TypeScript

// 事件名称与其监听器参数之间的映射 type EventListenerArgs = { // 在所有元素初始化并添加后触发 initialized: [instance: OverlayScrollbars]; // 在更新后触发 updated: [instance: OverlayScrollbars, onUpdatedArgs: OnUpdatedEventListenerArgs]; // 在所有元素、观察者和事件销毁后触发 destroyed: [instance: OverlayScrollbars, canceled: boolean]; // 在滚动时触发 scroll: [instance: OverlayScrollbars, event: Event]; }; 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 实例。

const osInstance = OverlayScrollbars(document.body, {});

实例方法

这是一个深入的主题。点击此处阅读。

options(): Options

获取实例的当前选项。

返回值描述
Options当前的选项

options(newOptions, pure?): Options

设置实例的当前选项。

参数类型描述
newOptionsPartialOptions应该应用的新(部分)选项。
pureboolean | undefined是否在添加新选项之前重置现有选项。
返回值描述
Options完整的新选项

on(eventListeners, pure?): Function

为实例添加事件监听器。

参数类型描述
eventListenersEventListeners包含添加的监听器的对象。字段是事件名称和监听器。
pureboolean | undefined是否在添加新监听器之前移除所有已经添加的监听器。
返回值描述
Function一个函数,用于移除所有已添加的事件监听器。

on(name, listener): Function

为实例添加单个事件监听器。

参数类型描述
namestring事件名称
listenerFunction当事件被触发时调用的函数
返回值描述
Function一个函数,用于移除已添加的事件监听器。

on(name, listeners): Function

为实例添加多个事件监听器。

参数类型描述
namestring事件名称
listenersFunction[]触发事件时调用的函数数组
返回值描述
Function一个函数,用于移除已添加的事件监听器。

off(name, listener): void

从实例中移除单个事件监听器。

参数类型描述
namestring事件名称
listenerFunction要移除的函数

off(name, listeners): void

从实例中移除多个事件监听器。

参数类型描述
namestring事件名称
listenersFunction[]要移除的函数数组

update(force?): boolean

更新实例。

参数类型描述
forceboolean | undefined是否强制使缓存失效并进行更新。
返回值描述
boolean一个布尔值,指示 update 事件是否通过此更新被触发。

state(): State

获取实例的状态。

返回值描述
State描述实例状态的对象

elements(): Elements

获取实例的元素。

返回值描述
Elements描述实例元素的对象

destroy(): void

销毁实例并移除所有已添加的元素。

plugin(plugin: object): object | undefined

获取传入插件的实例模块。

返回值描述
object | undefined描述插件实例模块的对象,如果未找到实例,则返回 undefined

TypeScript

// 简化版的 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 对象。

OverlayScrollbars.plugin(SomePlugin);

静态对象方法

这是一个深入的主题。点击此处阅读。

valid(osInstance): boolean

检查传入的值是否为有效且未销毁的 OverlayScrollbars 实例。

参数类型描述
osInstanceany需要检查的值
返回值描述
boolean传入的值是否是一个有效且未销毁的 OverlayScrollbars 实例。

env(): Environment

获取环境信息。

返回值描述
Environment描述环境信息的对象

nonce(newNonce): void

设置内联样式的 nonce 属性。

参数类型描述
newNoncestring | undefined内联样式的 nonce 属性

plugin(plugin): object | undefined

添加单个插件。

参数类型描述
pluginobject要添加的插件
返回值描述
object | void描述插件的静态模块实例的对象,如果未找到实例,则返回 void

plugin(plugins): (object | void)[]

添加多个插件。

参数类型描述
pluginsobject[]要添加的插件数组
返回值描述
(object | void)[]描述插件的静态模块实例的数组,如果未找到实例,则返回 undefined

TypeScript

// 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-darkos-theme-light。您可以使用 scrollbars.theme 选项来更改主题。

自定义主题可以通过多种方式实现。最简单且最快的方法是使用预定义的 CSS Custom Properties,也就是 CSS 变量。如果这些不够用,您还可以添加自定义类名,或者对现有类名添加自定义样式。

样式深入解析

这是一个深入的主题。点击此处阅读。

CSS 自定义属性

OverlayScrollbars 提供了一组 CSS Custom Properties,使得滚动条样式的定制变得简单而快速:

.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 作为主题名称:

// 水平和垂直滚动条的大小均为 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 选项来使用您的主题:

OverlayScrollbars(document.body, { scrollbars: { theme: 'os-theme-custom' } });

由于滚动条样式通常比较简单,这一组选项应该足以让您实现所需的样式。如果您需要更多自由度,您可以通过向下一个章节描述的基础类名添加样式来建自己的样式。

滚动条结构和 CSS 类名

滚动条的 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 是否符合预期。

插件

任何不被视为核心功能或用于旧版浏览器兼容性的功能,都通过插件进行扩展。这是为了确保所有未使用的插件在树摇(treeshaking)过程中被省略,从而不会出现在最终的打包文件中。OverlayScrollbars 附带了以下插件:

使用插件

插件的使用方式如下:

import { OverlayScrollbars, ScrollbarsHidingPlugin, SizeObserverPlugin, ClickScrollPlugin } from 'overlayscrollbars'; // 单个插件 OverlayScrollbars.plugin(ScrollbarsHidingPlugin); // 多个插件 OverlayScrollbars.plugin([SizeObserverPlugin, ClickScrollPlugin]);

插件深入解析

这是一个深入的话题。点击这里阅读。


插件是具有 单一字段 的普通对象,字段的名称就是插件的名称。这个名称是插件的标识符,必须 在所有插件中是唯一的。如果多个插件具有相同的名称,最后添加的插件会覆盖之前使用相同名称添加的插件。

插件模块

插件模块是插件模块实例的构造器。插件模块有两种类型:静态实例。一个插件必须至少有一个模块。插件模块可以返回一个实例,但不一定返回。

静态插件模块

静态 插件模块在使用 OverlayScrollbars.plugin 函数添加插件时被调用。

具有 静态 模块的插件示例:

const staticPlugin = { // 插件名称为 `examplePlugin`。 examplePlugin: { // `static` 函数描述了一个静态模块,并返回模块实例,或者如果不需要实例则返回 `void` 或 `undefined`。 // `osStatic` 参数是全局的 `OverlayScrollbars` 对象。 static: (osStatic) => { let count = 0; const staticPluginModuleInstance = { getCount: () => count, increment: () => { count++ }, } return staticPluginModuleInstance; } } }

当插件通过 OverlayScrollbars.plugin 函数添加时,静态模块实例会被返回:

const staticModuleInstance = OverlayScrollbars.plugin(staticPlugin); // 调用插件的静态模块 staticModuleInstance.count; // 0 staticModuleInstance.increment(); staticModuleInstance.count; // 1

实例插件模块

实例 插件模块在创建新的 OverlayScrollbars 实例时被调用,但在分发 initialized 事件之前。

具有 实例 模块的插件示例:

const instancePlugin = { // 插件名称为 `examplePlugin`。 examplePlugin: { // `instance` 函数描述了一个实例模块,并返回模块实例,或者如果不需要实例则返回 `void` 或 `undefined`。 // `osInstance` 参数是插件绑定到的 `OverlayScrollbar` 实例。 // `event` 参数是一个函数,用于向实例添加事件,这些事件无法在插件外部移除。 // `osStatic` 参数是全局的 `OverlayScrollbar` 对象。 instance: (osInstance, event, osStatic) => { let count = 0; const instancePluginModuleInstance = { getCount: () => count, increment: () => { count++ }, } // 实例初始化时触发的事件。 event('initialized', () => { console.log("实例已初始化"); }); // 视口滚动时触发的事件。 const removeScrollEvent = event('scroll', () => { console.log("视口已滚动"); removeScrollEvent(); // 滚动后移除事件。 }); return instancePluginModuleInstance; } } }

当插件通过 OverlayScrollbars.plugin 函数添加时,从那时起,所有的 OverlayScrollbar 实例将自动添加该插件。之前创建的实例将不会包含该插件。实例模块实例通过 osInstance.plugin 函数返回:

OverlayScrollbars.plugin(instancePlugin); // 插件被添加 const osInstance = OverlayScrollbars(document.body, {}); // 插件的实例模块被调用 const instancePluginInstance = osInstance.plugin(instancePlugin); instancePluginInstance.count; // 0 instancePluginInstance.increment(); instancePluginInstance.count; // 1

TypeScript

// 描述一个 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>; // 推断传入插件的静态模块实例类型。 type InferStaticPluginModuleInstance<T extends StaticPlugin>; // 推断传入插件的实例模块实例类型。 type InferInstancePluginModuleInstance<T extends InstancePlugin>;

常见问题

如何 获取/设置 我应用了 OverlayScrollbars 的元素的 滚动位置


如果你将 OverlayScrollbars 应用到 body 元素上,你可以使用 window.scrollXwindow.scrollYwindow.scrollwindow.scrollTowindow.scrollBy 或任何其他原生 API。

如果插件应用到其他元素上,你首先需要通过 instance.elements() 函数获取 viewport 元素。获取到这个元素后,你可以使用 element.scrollTopelement.scrollLeftelement.scrollelement.scrollToelement.scrollBy 或任何其他原生 API。

const { viewport } = osInstance.elements(); const { scrollLeft, scrollTop } = viewport; // 获取滚动偏移 viewport.scrollTo({ top: 0 }); // 设置滚动偏移

是否可以 限制 / 调整滚动条滑块长度


你可以通过设置 min-width / min-heightmax-width / max-height 样式来调整滚动条的滑块长度:

/* 水平边界 */ .os-scrollbar-horizontal .os-scrollbar-handle { min-width: 50px; max-width: 200px; } /* 垂直边界 */ .os-scrollbar-vertical .os-scrollbar-handle { min-height: 40px; max-height: 40px; }

你可以将两个属性设置为相同的值,以强制滚动条始终保持相同的大小。 设置 widthheight 属性是无效的,因为这些属性是由插件自动设置的。

v1 的功能比较

未来计划

许可证

MIT