Custom CSS-styled scrollbars that replace browser defaults while maintaining native scroll behavior and performance.
npx @tessl/cli install tessl/npm-simplebar@6.3.0SimpleBar is a JavaScript library that replaces browser default scrollbars with custom CSS-styled scrollbars while maintaining native scroll behavior and performance. It provides both automatic initialization via HTML attributes and manual instantiation for programmatic control.
This is the core vanilla JavaScript/TypeScript package from the SimpleBar monorepo, which also includes framework-specific variants for React, Vue, and Angular.
npm install simplebarimport SimpleBar from "simplebar";
import "simplebar/dist/simplebar.css";For CommonJS:
const SimpleBar = require("simplebar");
require("simplebar/dist/simplebar.css");For browser via CDN:
<link rel="stylesheet" href="https://unpkg.com/simplebar@latest/dist/simplebar.css" />
<script src="https://unpkg.com/simplebar@latest/dist/simplebar.min.js"></script>import SimpleBar from "simplebar";
// Automatic initialization via HTML attribute
// <div data-simplebar>Content to be scrolled</div>
// Manual initialization
const scrollableEl = document.getElementById('myScrollableDiv');
const simpleBar = new SimpleBar(scrollableEl, {
autoHide: false,
scrollbarMinSize: 30
});
// Access the scrollable element for events
simpleBar.getScrollElement().addEventListener('scroll', () => {
console.log('Scrolled!');
});SimpleBar is built around several key components:
data-simplebar attributesPrimary SimpleBar class with constructor, configuration options, and instance methods for creating and managing custom scrollbars.
class SimpleBar extends SimpleBarCore {
constructor(element: HTMLElement, options?: SimpleBarOptions);
// Static properties from SimpleBarCore
static helpers: {
getElementWindow(element: Element): Window;
getElementDocument(element: Element): Document;
getOptions(attributes: NamedNodeMap): SimpleBarOptions;
addClasses(el: HTMLElement | null, classes: string): void;
removeClasses(el: HTMLElement | null, classes: string): void;
classNamesToQuery(classNames: string): string;
canUseDOM: boolean;
};
static getOptions: (attributes: NamedNodeMap) => SimpleBarOptions;
static defaultOptions: SimpleBarOptions;
static getRtlHelpers(): RtlHelpers | null;
static getOffset(el: Element): { top: number; left: number };
// Instance properties
el: HTMLElement;
options: SimpleBarOptions;
classNames: ClassNames;
axis: { x: AxisProps; y: AxisProps };
// Instance methods
getScrollElement(): HTMLElement | null;
getContentElement(): HTMLElement | null;
recalculate(): void;
unMount(): void;
}
interface SimpleBarOptions {
forceVisible?: boolean | 'x' | 'y';
clickOnTrack?: boolean;
scrollbarMinSize?: number;
scrollbarMaxSize?: number;
classNames?: Partial<ClassNames>;
ariaLabel?: string;
tabIndex?: number;
scrollableNode?: HTMLElement | null;
contentNode?: HTMLElement | null;
autoHide?: boolean;
}Automatic scrollbar initialization using HTML data attributes and global DOM observation for dynamic content.
// Static methods
static initDOMLoadedElements(): void;
static initHtmlApi(): void;
static removeObserver(): void;
static handleMutations(mutations: MutationRecord[]): void;
// Static properties
static instances: WeakMap<Node, SimpleBar>;
static globalObserver: MutationObserver;Comprehensive configuration options for scrollbar behavior, appearance, and accessibility features.
interface ClassNames {
contentEl: string;
contentWrapper: string;
offset: string;
mask: string;
wrapper: string;
placeholder: string;
scrollbar: string;
track: string;
heightAutoObserverWrapperEl: string;
heightAutoObserverEl: string;
visible: string;
horizontal: string;
vertical: string;
hover: string;
dragging: string;
scrolling: string;
scrollable: string;
mouseEntered: string;
}type Axis = 'x' | 'y';
interface AxisProps {
scrollOffsetAttr: 'scrollLeft' | 'scrollTop';
sizeAttr: 'width' | 'height';
scrollSizeAttr: 'scrollWidth' | 'scrollHeight';
offsetSizeAttr: 'offsetWidth' | 'offsetHeight';
offsetAttr: 'left' | 'top';
overflowAttr: 'overflowX' | 'overflowY';
dragOffset: number;
isOverflowing: boolean;
forceVisible: boolean;
track: {
size: number | null;
el: HTMLElement | null;
rect: DOMRect | null;
isVisible: boolean;
};
scrollbar: {
size: number | null;
el: HTMLElement | null;
rect: DOMRect | null;
isVisible: boolean;
};
}
interface RtlHelpers {
isScrollOriginAtZero: boolean;
isScrollingToNegative: boolean;
}