OverlayScrollbars
A javascript scrollbar plugin that hides the native scrollbars, provides custom styleable overlay scrollbars, and preserves the native functionality and feel.
Why?
I created this plugin because I hate ugly and space-consuming scrollbars. Similar plugins didn't meet my requirements in terms of features, quality, simplicity, license or browser support.
Goals & Features
- Simple, powerful and well-documented API.
- High browser compatibility - Firefox 59+, Chrome 55+, Opera 42+, Edge 15+ and Safari 10+.
- Fully Accessible - Native scrolling behavior is fully preserved.
- Can run on the server (
Node, Deno and Bun) - SSR, SSG and ISR support.
- Tested on various devices - Mobile, Desktop and Tablet.
- Tested with various (and mixed) inputs - Mouse, Touch and Pen.
- Treeshaking - bundle only what you really need.
- Automatic update detection - no polling required.
- Leverage latest browser features - best performance in new browsers.
- Flow independent - supports all values for
direction, flex-direction and writing-mode.
- Supports scroll snapping.
- Supports all virtual scrolling libraries.
- Supports the
body element.
- Easy and effective scrollbar styling.
- Highly customizable.
- TypeScript support - completely written in TypeScript.
- Dependency-free - 100% self-written to ensure small size and best functionality.
- High quality and fully typed framework versions for
react, vue, angular, svelte and solid.
Choose your framework
In addition to the vanilla JavaScript version, you can use the official framework components & utilities:

Getting started
npm & nodejs
OverlayScrollbars can be downloaded from npm or the package manager of your choice:
npm install overlayscrollbars
Once installed, it can be imported:
import 'overlayscrollbars/overlayscrollbars.css';
import {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin
} from 'overlayscrollbars';
Note: If the path 'overlayscrollbars/overlayscrollbars.css' is not working use 'overlayscrollbars/styles/overlayscrollbars.css' as the import path for the CSS file.
You can use this Node Example as an reference / starting point.
Manual Download & Embedding
You can use OverlayScrollbars without any bundler or package manager.
Simply download one of the Releases or use a CDN.
- Use the javascript files with the
.browser extension.
- Use the javascript files with the
.es5 extension if you need to support older browsers, otherwise use the .es6 files.
- For production use the javascript / stylesheet files with the
.min extension.
Embed OverlayScrollbars manually in your 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>
Use the global variable OverlayScrollbarsGlobal to access the api similar to how you can do it in nodejs / modules:
var {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin
} = OverlayScrollbarsGlobal;
You can use this Browser Example as an reference or a starting point.
The examples in this documentation use the import syntax instead of the OverlayScrollbarsGlobal object. However, both versions are equivalent.
Initialization
The initialization of OverlayScrollbars is explicit per element. Only the scrollbars of the element on which the plugin is initialized will be changed. Scrollbars of child elements will remain unchanged unless the plugin is initialized on them as well.
You can either initialize a new instance directly with an Element or with an Object where you have more control over the initialization process.
const osInstance = OverlayScrollbars(document.querySelector('#myElement'), {});
Bridging initialization flickering
When you initialize OverlayScrollbars, it takes a few milliseconds to create and append all the elements to the DOM. During this time, the native scrollbars are still visible and will be switched out after the initialization is finished. This is seen as flickering.
To fix this behavior apply the data-overlayscrollbars-initialize attribute to the target element (and the html element as well when initializing a scrollbar for the body element).
<html data-overlayscrollbars-initialize>
<head></head>
<body data-overlayscrollbars-initialize></body>
</html>
<div data-overlayscrollbars-initialize>
OverlayScrollbars is applied to this div
</div>
Initialization with an Object
This is an in depth topic. Click here to read it.
The only required field is the target field. This is the field to which the plugin will be applied.
If you use the object initialization with only the target field, the result is equivalent to the element initialization:
OverlayScrollbars(document.querySelector('#myElement'), {});
OverlayScrollbars({ target: document.querySelector('#myElement') }, {});
When initializing with an object you can specify how the library handles generated elements.
For example, you can specify an existing element as the `viewport' element. Then the library won't generate it, but use the specified element instead:
OverlayScrollbars({
target: document.querySelector('#target'),
elements: {
viewport: document.querySelector('#viewport'),
},
}, {});
This is very useful if you have a fixed DOM structure and don't want OverlayScrollbars to create its own elements. These cases are very common when you want another library to work with OverlayScrollbars.
You can also decide to which element the scrollbars should be applied to:
OverlayScrollbars({
target: document.querySelector('#target'),
scrollbars: {
slot: document.querySelector('#target').parentElement,
},
}, {});
Last but not least, you can decide when to cancel the initialization:
OverlayScrollbars({
target: document.querySelector('#target'),
cancel: {
nativeScrollbarsOverlaid: true,
body: null,
}
}, {});
In the above example, the initialization will be aborted if the native scrollbars are overlaid, or if your target is a body element and the plugin has determined that initializing to the body element would interfere with native functionality such as window.scrollTo.
Styling
OverlayScrollbars provides a set of CSS Custom Properties which makes styling easy and fast.
Out of the box you can choose between two scrollbar themes called os-theme-dark and os-theme-light. You can use the scrollbars.theme option to change the theme.
Custom scrollbar themes can be done in several ways. The easiest and fastest way is to use the predefined set of CSS Custom Properties aka CSS variables. If that's not enough, you can add custom class names or add custom styling to the existing class names.
Styling in depth
This is an in depth topic. Click here to read it.
CSS Custom properties
OverlayScrollbars provides the following CSS Custom Properties:
Viewport styling:
[data-overlayscrollbars-viewport] {
overflow-x: var(--os-viewport-overflow-x);
overflow-y: var(--os-viewport-overflow-y);
}
You can use the --os-viewport-overflow-x and --os-viewport-overflow-y properties to re-apply the correct overflow styles in case other styling rules (e.g. from 3rd party libraries) are overwriting them.
Scrollbar styling:
.os-scrollbar {
--os-size: 0;
--os-padding-perpendicular: 0;
--os-padding-axis: 0;
--os-track-border-radius: 0;
--os-track-bg: none;
--os-track-bg-hover: none;
--os-track-bg-active: none;
--os-track-border: none;
--os-track-border-hover: none;
--os-track-border-active: none;
--os-handle-border-radius: 0;
--os-handle-bg: none;
--os-handle-bg-hover: none;
--os-handle-bg-active: none;
--os-handle-border: none;
--os-handle-border-hover: none;
--os-handle-border-active: none;
--os-handle-min-size: 33px;
--os-handle-max-size: none;
--os-handle-perpendicular-size: 100%;
--os-handle-perpendicular-size-hover: 100%;
--os-handle-perpendicular-size-active: 100%;
--os-handle-interactive-area-offset: 0;
}
You can change the properties for both scrollbars at once, or for each scrollbar axis. In the example below, I've chosen os-theme-custom as the theme name:
.os-theme-custom {
--os-size: 10px;
}
.os-theme-custom.os-scrollbar-horizontal {
--os-size: 10px;
}
.os-theme-custom.os-scrollbar-vertical {
--os-size: 20px;
}
You can then use your theme by assigning it via the scrollbars.theme option:
OverlayScrollbars(document.body, {
scrollbars: {
theme: 'os-theme-custom'
}
});
Since scrollbar styles are usually simple, this set of options should be enough to get the styling you want.
If you need more freedom, you can create your own styles by adding styling to the base class names described in the next section.
Scrollbars structure and CSS class names
The scrollbars HTML markup looks like:
<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>
The class names are simplified, in a real application the .os-scrollbar element can have additional class names which modify the appearance (mostly visibility and alignment).
Below is a list of the most important class names you will encounter:
.os-scrollbar | The root element of a scrollbar. |
.os-scrollbar-rtl | Indicates a RTL direction of the host element the scrollbar belongs to. |
.os-scrollbar-horizontal | The root element of a horizontal scrollbar. |
.os-scrollbar-vertical | The root element of a vertical scrollbar. |
.os-scrollbar-handle-interactive | Indicates that the handle inside the scrollbar is interactive (scrollbars.dragScroll is not false). |
.os-scrollbar-track-interactive | Indicates that the track inside the scrollbar is interactive (scrollbars.clickScroll is not false). |
.os-scrollbar-track | The track element. This is the track of the nested handle element. If scrollbars.clickScroll is not false this is the element users can click to change the scroll offset. |
.os-scrollbar-handle | The handle element. If scrollbars.dragScroll is not false this is the handle users can drag to change the scroll offset. |
If you create your own theme, please only use the classes listed above. All other classes are modifier classes used to change visibility, alignment and pointer-events of the scrollbars.
Gotchas
It is important that the chosen theme class name in your CSS file matches the assigned theme name in the options. If the CSS class name is .my-theme, the scrollbars.theme must be 'my-theme'.
Please be aware of your stack. For example, css-modules will change your class names to avoid naming collisions. Always check that your CSS is what you expect it to be.
Options
You can initialize OverlayScrollbars with an initial set of options, which can be changed at any time with the options method:
OverlayScrollbars(document.querySelector('#myElement'), {
overflow: {
x: 'hidden',
},
});
Options in depth
This is an in depth topic. Click here to read it.
The default options are:
const defaultOptions = {
paddingAbsolute: false,
showNativeOverlaidScrollbars: false,
update: {
elementEvents: [['img', 'load']],
debounce: {
mutation: [0, 33],
resize: null,
event: [33, 99],
env: [222, 666, true],
},
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
Indicates whether the padding for the content should be absolute.
showNativeOverlaidScrollbars
Indicates whether the native overlaid scrollbars should be visible.
update.elementEvents
Array<[string, string]> | null | [['img', 'load']] |
An array of tuples. The first value in the tuple is an selector and the second value are event names. The plugin will update itself if any of the elements with the specified selector emits any of the specified events. The default value can be interpreted as "The plugin will update itself if any img element emits a load event."
update.debounce
Options to debounce updates to fine-tune performance.
Each field in this object has the following type:
[timeout?: number, maxWait?: number, leading?: boolean] | number | null | null |
The tuple type of [timeout?: number, maxWait?: number, leading?: boolean] has three values:
- timeout: The timeout of the debounce in milliseconds.
- maxWait: The max wait of the debounce in milliseconds.
- leading: Indicates whether the debounce is also executed on the leading edge.
If a number is specified it is treated as the timeout in milliseconds.
If null is specified no debounce will take place.
Note: If 0 is used as the timeout, requestAnimationFrame will be used instead of setTimeout for the debounce.
update.debounce.mutation
[timeout?: number, maxWait?: number, leading?: boolean] | number | null | [0, 33] |
Debounce updates which were triggered by a MutationObserver.
update.debounce.resize
[timeout?: number, maxWait?: number, leading?: boolean] | number | null | null |
Debounce updates which were triggered by a ResizeObserver.
update.debounce.event
[timeout?: number, maxWait?: number, leading?: boolean] | number | null | [33, 99] |
Debounce updates which were triggered by an event registered in the update.elementEvents option.
update.debounce.env
[timeout?: number, maxWait?: number, leading?: boolean] | number | null | [222, 666, true] |
Debounce updates which were triggered by environmental changes. (e.g. zooming & window resize)
update.attributes
Note: There is a base array of attributes that the MutationObserver always observes, even if this option is null.
An array of additional attributes that the MutationObserver should observe the content for.
update.ignoreMutation
((mutation) => any) | null | null |
A function which receives a MutationRecord as an argument. If the function returns a truthy value the mutation will be ignored and the plugin won't update. Useful to fine-tune performance.
overflow.x
Note: Valid values are: 'hidden', 'scroll', 'visible', 'visible-hidden' and 'visible-scroll'.
The overflow behavior for the horizontal (x) axis.
overflow.y
Note: Valid values are: 'hidden', 'scroll', 'visible', 'visible-hidden' and 'visible-scroll'.
The overflow behavior for the vertical (y) axis.
scrollbars.theme
string | null | 'os-theme-dark' |
Applies the specified theme (classname) to the scrollbars.
scrollbars.visibility
Note: Valid values are: 'visible', 'hidden', and 'auto'.
The visibility of a scrollbar if its scroll axis is able to have a scrollable overflow. (Scrollable overflow for an axis is only possible with the overflow behavior set to 'scroll' or 'visible-scroll').
scrollbars.autoHide
Note: Valid values are: 'never', 'scroll', 'leave' and 'move'.
Dictates whether to hide visible scrollbars automatically after a certain user action.
scrollbars.autoHideDelay
The delay in milliseconds before the scrollbars are automatically hidden.
scrollbars.autoHideSuspend
Suspend the autoHide functionality until the first scroll interaction is performed.
The default value for this option is false for backwards compatibility reasons but is recommended to be true for better accessibility.
scrollbars.dragScroll
Indicates whether you can drag the scrollbar handles for scrolling.
scrollbars.clickScroll
Note: If set to true the ClickScrollPlugin is required.
Indicates whether you can click on the scrollbar track for scrolling.
scrollbars.pointers
string[] | null | ['mouse', 'touch', 'pen'] |
The PointerTypes the plugin should react to.
TypeScript
type Options = {
paddingAbsolute: boolean;
showNativeOverlaidScrollbars: boolean;
update: {
elementEvents: Array<[elementSelector: string, eventNames: string]> | null;
debounce: {
mutation: [timeout?: number, maxWait?: number, leading?: boolean] | number | null;
resize: [timeout?: number, maxWait?: number, leading?: boolean] | number | null;
event: [timeout?: number, maxWait?: number, leading?: boolean] | number | null;
env: [timeout?: number, maxWait?: number, leading?: boolean] | number | null;
};
attributes: string[] | null;
ignoreMutation: ((mutation: MutationRecord) => any) | null;
};
overflow: {
x: OverflowBehavior;
y: OverflowBehavior;
};
scrollbars: {
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-scroll';
type ScrollbarsVisibilityBehavior =
| 'visible'
| 'hidden'
| 'auto';
type ScrollbarsAutoHideBehavior =
| 'never'
| 'scroll'
| 'move'
| 'leave';
type ScrollbarsClickScrollBehavior = boolean | 'instant';
Events
You can initialize OverlayScrollbars with an initial set of events, which can be managed at any time with the on and off methods:
OverlayScrollbars(document.querySelector('#myElement'), {}, {
updated(osInstance, onUpdatedArgs) {
}
});
Events in depth
This is an in depth topic. Click here to read it.
Note: Every event receives the instance from which it was dispatched as the first argument. Always.
initialized
instance | The instance which dispatched the event. |
Dispatched after all generated elements, observers and events were appended to the DOM.
updated
instance | The instance which dispatched the event. |
onUpdatedArgs | An object which describes the update in detail. |
Note: If an update was triggered but nothing changed, the event won't be dispatched.
Dispatched after the instance was updated.
destroyed
instance | The instance which dispatched the event. |
canceled | A boolean which indicates whether the initialization was canceled and thus destroyed. |
Dispatched after all generated elements, observers and events were removed from the DOM.
scroll
instance | The instance which dispatched the event. |
event | The original event argument of the DOM event. |
Dispatched by scrolling the viewport.
TypeScript
type EventListenerArgs = {
initialized: [instance: OverlayScrollbars];
updated: [instance: OverlayScrollbars, onUpdatedArgs: OnUpdatedEventListenerArgs];
destroyed: [instance: OverlayScrollbars, canceled: boolean];
scroll: [instance: OverlayScrollbars, event: Event];
};
interface OnUpdatedEventListenerArgs {
updateHints: {
sizeChanged: boolean;
directionChanged: boolean;
heightIntrinsicChanged: boolean;
overflowEdgeChanged: boolean;
overflowAmountChanged: boolean;
overflowStyleChanged: boolean;
scrollCoordinatesChanged: boolean;
hostMutation: boolean;
contentMutation: boolean;
};
changedOptions: PartialOptions;
force: boolean;
}
Instance
The OverlayScrollbars instance can be created by calling the OverlayScrollbars function with an element and options object.
const osInstance = OverlayScrollbars(document.body, {});
Instance Methods
This is an in depth topic. Click here to read it.
options(): Options
Get the current options of the instance.
Options | The current options. |
options(newOptions, pure?): Options
Sets the current options of the instance.
| newOptions | PartialOptions | The new (partial) options which should be applied. |
| pure | boolean | undefined | Whether the options should be reset before the new options are added. |
Options | The complete new options. |
on(eventListeners, pure?): Function
Adds event listeners to the instance.
| eventListeners | EventListeners | An object which contains the added listeners. The fields are the event names and the listeners. |
| pure | boolean | undefined | Whether all already added event listeners should be removed before the new listeners are added. |
Function | A function which removes all added event listeners. |
on(name, listener): Function
Adds a single event listener to the instance.
| name | string | The event name. |
| listener | Function | The function invoked when the event is dispatched. |
Function | A function which removes the added event listener. |
on(name, listeners): Function
Adds multiple event listeners to the instance.
| name | string | The event name. |
| listeners | Function[] | The functions invoked when the event is dispatched. |
Function | A function which removes the added event listeners. |
off(name, listener): void
Removes a single event listener from the instance.
| name | string | The event name. |
| listener | Function | The function to be removed. |
off(name, listeners): void
Removes multiple event listeners from the instance.
| name | string | The event name. |
| listeners | Function[] | The functions to be removed. |
update(force?): boolean
Updates the instance.
| force | boolean | undefined | Whether the update should force the cache to be invalidated. |
Function | A boolean which indicates whether the update event was triggered through this update. |
state(): State
Gets the instance's state.
State | An object describing the state of the instance. |
elements(): Elements
Gets the instances elements.
Elements | An object describing the elements of the instance. |
destroy(): void
Destroys the instance and removes all added elements.
plugin(plugin: object): object | undefined
Gets the instance modules instance of the passed plugin.
object | undefined | An object which describes the plugins instance modules instance or undefined if no instance was found. |
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;
}
interface State {
padding: TRBL;
paddingAbsolute: boolean;
overflowEdge: XY<number>;
overflowAmount: XY<number>;
overflowStyle: XY<OverflowStyle>;
hasOverflow: XY<boolean>;
scrollCoordinates: {
start: XY<number>;
end: XY<number>;
};
directionRTL: boolean;
destroyed: boolean;
}
interface Elements {
target: HTMLElement;
host: HTMLElement;
padding: HTMLElement;
viewport: HTMLElement;
content: HTMLElement;
scrollOffsetElement: HTMLElement;
scrollEventElement: HTMLElement | Document;
scrollbarHorizontal: CloneableScrollbarElements;
scrollbarVertical: CloneableScrollbarElements;
}
Static Object
The static OverlayScrollbars object.
OverlayScrollbars.plugin(SomePlugin);
Static Object Methods
This is an in depth topic. Click here to read it.
valid(osInstance): boolean
Checks whether the passed value is a valid and not destroyed overlayscrollbars instance
| osInstance | any | The value to be checked. |
boolean | Whether the passed value is a valid and not destroyed overlayscrollbars instance. |
env(): Environment
Gets the environment.
Environment | An object describing the environment. |
nonce(newNonce): void
Sets the nonce attribute for inline styles.
| newNonce | string | undefined | The new nonce attribute for inline styles. |
trustedTypePolicy(newTrustedTypePolicy): void
Sets the trusted type policy.
| newTrustedTypePolicy | TrustedTypePolicy | undefined | The new trusted type policy. |
plugin(plugin): object | undefined
Adds a single plugin.
| plugin | object | The plugin to be added. |
object | void | An object describing the plugin's static module instance or void if no instance was found. |
plugin(plugins): (object | void)[]
Adds multiple plugins.
| plugins | object[] | The plugins to be added. |
(object | void)[] | An array describing the plugins static modules instances or undefined if no instance was found. |
TypeScript
interface OverlayScrollbarsStatic {
(target: InitializationTarget): OverlayScrollbars | undefined;
(target: InitializationTarget, options: PartialOptions, eventListeners?: EventListeners): OverlayScrollbars;
valid(osInstance: any): osInstance is OverlayScrollbars;
env(): Environment;
nonce(newNonce: string | undefined): void;
plugin(plugin: Plugin): InferStaticPluginModuleInstance<Plugin>
plugin(plugins: Plugin[]): InferStaticPluginModuleInstance<Plugin>[];
}
interface Environment {
scrollbarsSize: XY<number>;
scrollbarsOverlaid: XY<boolean>;
scrollbarsHiding: boolean;
scrollTimeline: boolean;
staticDefaultInitialization: Initialization;
staticDefaultOptions: Options;
getDefaultInitialization(): Initialization;
getDefaultOptions(): Options;
setDefaultInitialization(newDefaultInitialization: PartialInitialization): Initialization;
setDefaultOptions(newDefaultOptions: PartialOptions): Options;
}
Plugins
Anything that is not considered core functionality or old browser compatibility is exposed via a plugin. This is done because all unused plugins are omitted during treeshaking and won't end up in your final bundle. OverlayScrollbars ships with the following plugins:
Consuming Plugins
Plugins are consumed like:
import {
OverlayScrollbars,
ScrollbarsHidingPlugin,
SizeObserverPlugin,
ClickScrollPlugin
} from 'overlayscrollbars';
OverlayScrollbars.plugin(ScrollbarsHidingPlugin);
OverlayScrollbars.plugin([SizeObserverPlugin, ClickScrollPlugin]);
Plugins in depth
This is an in depth topic. Click here to read it.
Plugins are plain objects with a single field, the name of the field is the name of the plugin. This name is the plugin's identifier and must be unique across all plugins. In case multiple plugins have the same name, the last added plugin overwrites the plugin added previously under the same name.
Plugin Modules
A Plugin module is the constructor of a plugin module's instance. There are two kinds of plugin modules: static and instance. A single plugin must have one or more modules. A plugin module can return an instance, but doesn't have to.
Static Plugin Module
The static plugin module is invoked when the plugin is added with the OverlayScrollbars.plugin function.
Example plugin with a static module:
const staticPlugin = {
examplePlugin: {
static: (osStatic) => {
let count = 0;
const staticPluginModuleInstance = {
getCount: () => count,
increment: () => { count++ },
}
return staticPluginModuleInstance;
}
}
}
When the plugin is added with the OverlayScrollbars.plugin function, the static module instance is returned:
const staticModuleInstance = OverlayScrollbars.plugin(staticPlugin);
staticModuleInstance.count;
staticModuleInstance.increment();
staticModuleInstance.count;
Instance Plugin Module
The instance plugin module is invoked when a new OverlayScrollbars instance is created but before the initialized event is dispatched.
Example plugin with a instance module:
const instancePlugin = {
examplePlugin: {
instance: (osInstance, event, osStatic) => {
let count = 0;
const instancePluginModuleInstance = {
getCount: () => count,
increment: () => { count++ },
}
event('initialized', () => {
console.log("instance initialized");
});
const removeScrollEvent = event('scroll', () => {
console.log("viewport scrolled");
removeScrollEvent();
});
return instancePluginModuleInstance;
}
}
}
When the plugin is added with the OverlayScrollbars.plugin function, all OverlayScrollbar instances will automatically add the plugin from that point on. Previously created instances will not have the plugin. The instance module instance is returned with the osInstance.plugin function:
OverlayScrollbars.plugin(instancePlugin);
const osInstance = OverlayScrollbars(document.body, {});
const instancePluginInstance = osInstance.plugin(instancePlugin);
instancePluginInstance.count;
instancePluginInstance.increment();
instancePluginInstance.count;
TypeScript
type Plugin<
Name extends string = string,
S extends PluginModuleInstance | void = PluginModuleInstance | void,
I extends PluginModuleInstance | void = PluginModuleInstance | void
> = {
[pluginName in Name]: PluginModule<S, I>;
};
type StaticPlugin<
Name extends string = string,
T extends PluginModuleInstance = PluginModuleInstance
> = Plugin<Name, T, void>;
type InstancePlugin<
Name extends string = string,
T extends PluginModuleInstance = PluginModuleInstance
> = Plugin<Name, void, T>;
type InferStaticPluginModuleInstance<T extends StaticPlugin>;
type InferInstancePluginModuleInstance<T extends InstancePlugin>;
FAQ
How do I get / set the scroll position of an element I applied OverlayScrollbars to?
If you applied OverlayScrollbars to the body element you can use window.scrollX, window.scrollY, window.scroll, window.scrollTo, window.scrollBy or any other native api.
If the plugin was applied to any other element you have to get the viewport element with the instance.elements() function first. With this element you can use element.scrollTop, element.scrollLeft, element.scroll, element.scrollTo, element.scrollBy or any other native api.
const { viewport } = osInstance.elements();
const { scrollLeft, scrollTop } = viewport;
viewport.scrollTo({ top: 0 });
Is it possible to limit / adjust the scrollbar handle length?
You can adjust a scrollbar's handle length by setting a min-width / min-height and max-width / max-height style:
.os-scrollbar-horizontal .os-scrollbar-handle {
min-width: 50px;
max-width: 200px;
}
.os-scrollbar-vertical .os-scrollbar-handle {
min-height: 40px;
max-height: 40px;
}
You can assign the same value to both properties to force the scrollbar to be always the same size.
Setting the width and height properties won't work since those are set by the plugin automatically.
Feature comparison to v1
- The
scroll function is missing. Planned as a plugin. (WIP)
- Initialization to the
textarea element isn't supported yet. Planned as a plugin. (WIP)
Future Plans
- Provide plugin based support for missing features. (treeshakeable)
- Frequent updates in terms of bug-fixes and enhancements. (always use latest browser features)
- Improve tests. (unit & browser tests)
Used by
|
Thanks to BrowserStack for sponsoring open source projects and letting me test OverlayScrollbars for free.
|
License
MIT