simplebar
A lightweight, dependency-free library for replacing native scrollbars with a custom CSS-styled one, without sacrificing native scroll performance.
Repository Health
Technical Analysis
SimpleBar is a small JavaScript library that swaps the browser’s default scrollbar for a fully CSS-styleable one while keeping the underlying native overflow: auto scrolling behavior intact. Rather than reimplementing scroll physics in JavaScript, the approach many “custom scrollbar” plugins take and the one that causes jank, broken momentum scrolling, and platform-specific quirks, SimpleBar only swaps the visual chrome around a real native scroll container. The result is a scrollbar that can be restyled freely (color, width, radius, auto-hide behavior) with ordinary CSS, on an element that still scrolls exactly like the browser expects.
The library ships as a monorepo of independently versioned packages: the core simplebar package for vanilla JS/HTML usage (with automatic initialization via a data-simplebar attribute and a MutationObserver that picks up dynamically added elements), a shared simplebar-core engine that does the actual DOM wiring, and thin framework wrappers for React, Vue, and Angular that expose the same behavior as idiomatic components. At roughly 6kb minified with no required dependency for the vanilla build, it’s built for teams who want custom scrollbar styling without adopting a heavier UI framework or accepting a JS-driven scroll implementation.
What You Get
- A vanilla JS/CSS package (
simplebar) that auto-initializes on any element carrying adata-simplebarattribute, no manual JS wiring needed for the common case. - First-party framework wrappers,
simplebar-react,simplebar-vue(2.7 and 3), andsimplebar-angular, exposing the same scrollbar behavior as idiomatic components. - A shared
simplebar-coreengine handling scroll-position tracking, scrollbar drag/click-on-track interaction, RTL support, and MutationObserver-based content-resize detection. - Prebuilt minified JS and CSS bundles served via unpkg/jsdelivr for drop-in
<script>/<link>usage with no build step.
Common Use Cases
- Restyling scrollbars inside chat panels, sidebars, or modals to match a product’s design system instead of the OS-default scrollbar.
- Adding Mac-style auto-hiding scrollbars to a web app for a more native-feeling desktop experience across Windows/Linux browsers.
- Enabling RTL-aware custom scrollbars for internationalized applications without hand-rolling scroll-direction detection.
- Building custom scrollable UI (dropdowns, code blocks, data tables) in React/Vue/Angular apps via the matching wrapper package instead of reimplementing scrollbar styling per framework.
Under The Hood
Architecture
The core SimpleBarCore class (in simplebar-core) owns all DOM wiring: it builds a wrapper/offset/mask/content-wrapper structure around the target element, tracks scroll position via native scroll events, and renders draggable scrollbar/track elements whose size and position are recomputed on resize, mutation, and RTL-direction changes. The vanilla simplebar package is a thin subclass that adds automatic discovery of data-simplebar elements via DOMContentLoaded/load listeners and a global MutationObserver, keying already-instantiated nodes in a static WeakMap to avoid double-initialization or memory leaks. Framework packages (simplebar-react, simplebar-vue, simplebar-angular) each wrap this same core class as an idiomatic component, binding lifecycle hooks (mount/unmount) to instance creation and teardown. The whole project is a Lerna/Yarn-workspaces monorepo with each package independently versioned and built via Rollup, sharing simplebar-core as a common dependency, so any change to the core’s public API (the options object, recalculate, getScrollElement) has to stay backward compatible across all three framework wrappers at once.
Tech Stack
The codebase is primarily TypeScript (with a tsconfig.json in strict mode) compiled via Rollup with @rollup/plugin-typescript and Babel presets for env/React/TypeScript, producing ESM, CJS, and minified UMD/global builds plus a minified CSS bundle. Runtime dependencies are minimal, lodash-es for tree-shakeable debounce/throttle, with framework wrappers depending on their respective peer libraries (React, Vue 2/3, Angular). The monorepo is managed with Lerna and classic Yarn workspaces (with nohoist rules for webpack-related tooling), and releases are cut through the auto changelog tool feeding a Lerna publish flow with beta pre-release tags. There is no server-side or build-time runtime, this is a pure client-side library distributed for direct browser use via <script>/<link> tags served from unpkg/jsdelivr, as well as via npm for bundler-based projects.
Code Quality
Each package carries its own test suite: unit tests run under Jest with ts-jest and jest-environment-jsdom, complemented by Puppeteer-driven end-to-end tests (jest-puppeteer) that exercise real browser scroll/drag behavior a jsdom-only suite couldn’t validate, a sensible two-tier approach for a DOM-manipulation library. Linting is configured with ESLint plus @typescript-eslint, enforced pre-commit via Husky and lint-staged, and formatting is handled by Prettier. Naming is consistent and descriptive throughout (contentWrapperEl, scrollbarMinSize, etc.), and error handling is limited to defensive guard clauses (canUseDOM checks, null checks on DOM refs) rather than typed error results, which is standard for a UI/DOM library rather than a data-processing one. One notable gap: there’s no GitHub Actions CI workflow in the repository, only a legacy .travis.yml whose build badge is effectively stale, so automated checks on pull requests rely on contributors running lint/test/build locally rather than a CI gate.
API Design
Getting started requires close to zero boilerplate: install the package, import the JS and CSS, and add a data-simplebar attribute to any element, the MutationObserver-driven auto-init handles the rest with no manual instantiation needed for the common case. Manual control is available via new SimpleBar(el, options) with a small, consistent options object (autoHide, scrollbarMinSize, classNames, forceVisible, direction, clickOnTrack, ariaLabel, tabIndex) and instance methods (recalculate, getScrollElement, getContentElement) that mirror native DOM scrolling APIs, so migrating from plain overflow: auto requires no new mental model. Framework wrappers expose idiomatic component APIs (a React component, a Vue directive/component, an Angular directive) instead of forcing consumers to reach for the vanilla class directly. Documentation is thorough and example-driven, root and per-package READMEs plus a dedicated examples/ directory covering React, Vue, Angular, and jQuery, though it stops short of a generated API-reference site beyond README prose.
Used by 2 apps in this directory
Cosmos-Server
Security · Authentication
All-in-one self-hosted home server with SmartShield anti-DDoS, Nebula mesh VPN, automatic HTTPS, and a 250-app marketplace — all secured behind a unified auth layer.
Zulip
Team Chat
Topic-based team chat that brings the structure of email threads to real-time messaging, so distributed teams never lose context across hundreds of concurrent conversations.