npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

smooth-scrollbar-loco

v7.3.2

Published

Customize scrollbar in modern browsers with smooth scrolling experience.

Downloads

3

Readme

Smooth Scrollbar

npm npm npm Travis

Smooth scrolling in modern browsers.

Table of Contents

Install

Via npm:

npm install smooth-scrollbar --save

Via bower:

bower install smooth-scrollbar --save

Browser Compatibility

| Browser | Version | | :------ | :-----: | | IE | 10+ | | Chrome | 22+ | | Firefox | 16+ | | Safari | 8+ | | Android Browser | 4+ | | Chrome for Android | 32+ | | iOS Safari | 7+ |

Demo

http://idiotwu.github.io/smooth-scrollbar/

Why is native scrolling slow?

As is explained in this article, browser repaint every frame in scrolling. Less painting is better.

To avoid repainting, I use translate3d in scroll content to create composite layers and force hardware accelerating.

Usage

Smooth scrollbar is defined as an UMD module which named Scrollbar, you can use any loader to load it:

import Scrollbar from 'smooth-scrollbar';

Or get it from window object:

var Scrollbar = window.Scrollbar;

Don't forget to include the stylesheet in your page:

<link rel="stylesheet" href="dist/smooth-scrollbar.css">

There are three ways to tell the plugin which element should be a smooth scrollbar:

  1. As an element:

    <scrollbar>...</scrollbar>
  2. As an attribute:

    <section scrollbar>...</section>
  3. As a data attribute

    <section data-scrollbar>...</section>

Then init all scrollbars:

Scrollbar.initAll(options);

Or you can call Scrollbar.init(elem, options) to manually init the scrollbar:

Scrollbar.init(document.getElementById('my-scrollbar'), options);

Available Options for Scrollbar

| parameter | type | default | description | | :--------: | :--: | :-----: | :---------- | | speed | Number | 1 | Scrolling speed scale.| | damping | Number | 0.1 | Delta reduction damping, a float value between (0, 1), the lower the value is, the more smooth the scrolling will be. | | thumbMinSize | Number | 20 | Minimal size for scrollbar thumb. | | syncCallbacks | Boolean | false | Execute listeners in synchronous or asynchronous. | | renderByPixels | Boolean | true | Render scrolling by integer pixels, set to true to improve performance. | | alwaysShowTracks | Boolean | false | Keep scrollbar tracks visible whether it's scrolling or not. | | continuousScrolling | Boolean|String | 'auto' | Whether allow upper scrollable content to continue scrolling when current scrollbar reaches edge. When set to 'auto', it will be enabled on nested scrollbars, and disabled on first-class scrollbars. | | overscrollEffect | Boolean|String | false | Experimental overscroll effect, 'bounce' for iOS style effect and 'glow' for Android style effect. Be careful when you enable this feature! | | overscrollEffectColor | String | '#87ceeb' | Canvas paint color with 'glow' effect. | | overscrollDamping | Number | 0.2 | The same as damping, but for overscrolling. |

Confusing with the option field? Try edit tool here!

DOM Structure

Following is the DOM structure that Scrollbar yields:

<scrollbar>
    <article class="scroll-content">
        your contents here...
    </article>
    <aside class="scrollbar-track scrollbar-track-x">
        <div class="scrollbar-thumb scrollbar-thumb-x"></div>
    </aside>
    <aside class="scrollbar-track scrollbar-track-y">
        <div class="scrollbar-thumb scrollbar-thumb-y"></div>
    </aside>
</scrollbar>

APIs

In this documentation, we are using Scrollbar (in capitalized) to represent the constructor and scrollbar (in lowercase) for the instance object.

Static Methods

Scrollbar.init()

Scrollbar.init(elem, options?): SmoothScrollbar

| Param | Type | Description | | --- | :-: | --- | | elem | Element | The DOM element that you want to initialize scrollbar to. | | options | object, optional | Initial options, see Available Options for Scrollbar section above. |

Initializes a scrollbar on the given element and returns scrollbar instance:

var scrollbar = Scrollbar.init(document.body, { speed: 0.75 });

Scrollbar.initAll()

Scrollbar.init(options): [SmoothScrollbar]

| Param | Type | Description | | --- | :-: | --- | | options | object, optional | Initial options, see Available Options for Scrollbar section above. |

Automatically init scrollbar on all elements refer to the selector scrollbar, [scrollbar], [data-scrollbar], returns an array of scrollbars collection:

<scrollbar> ... </scrollbar>

<article scrollbar> ... </article>

<article data-scrollbar> ... </article>
Scrollbar.initAll(); // [ SmoothScrollbar, SmoothScrollbar, SmoothScrollbar ]

Scrollbar.has()

Scrollbar.has(elem): boolean

| Param | Type | Description | | --- | :-: | --- | | elem | Element | The DOM element that you want to check. |

Check if scrollbar exists on given element:

Scrollbar.init(document.body);

Scrollbar.has(document.body); // true

Scrollbar.get()

Scrollbar.get(elem): SmoothScrollbar

| Param | Type | Description | | --- | :-: | --- | | elem | Element | The DOM element that you want to check. |

Get scrollbar on the given element, if no scrollbar instance exsits, return undefined:

var scrollbar = Scrollbar.init(document.body);

Scrollbar.get(document.body) === scrollbar; // true

Scrollbar.get(document.documentElement); // undefined

Scrollbar.getAll()

Scrollbar.getAll(): [SmoothScrollbar]

Return an array that contains all scrollbar instances:

Scrollbar.getAll(); // [ SmoothScrollbar, SmoothScrollbar, ... ]

Scrollbar.destroy()

Scrollbar.destroy(elem): void

| Param | Type | Description | | --- | :-: | --- | | elem | Element | The DOM element that scrollbar is initialized to. |

Remove scrollbar on the given element.

Scrollbar.destroyAll()

Scrollbar.destroyAll(): void

Remove all scrollbar instances from current page.

Instance Properties and Methods

A scrollbar instance refer to what you get from Scrollbar.init() method:

var scrollbar = Scrollbar.init(elem)

scrollbar.targets

  • Type: object

An object that contains main parts of current scrollbar:

{
    container,
    content,
    xAxis: { track, thumb },
    yAxis: { track, thumb }
}

scrollbar.offset

  • Type: object

Current scrolling offset:

console.log(scrollbar.offset); // { x: 123, y: 456 }

scrollbar.limit

  • Type: object

Max-allowed scrolling distance:

console.log(scrollbar.limit); // { x: 1000, y: 1000 }

scrollbar.scrollTop

  • Type: number

Alias for scrollbar.offset.y:

console.log(scrollbar.scrollTop); // 123

console.log(scrollbar.scrollTop === scrollbar.offset.y); // true

scrollbar.scrollLeft

  • Type: number

Alias for scrollbar.offset.x:

console.log(scrollbar.scrollLeft); // 456

console.log(scrollbar.scrollLeft === scrollbar.offset.x); // true

scrollbar.wheelReversed

  • Type: boolean

Whether event wheel is reversed:

console.log(scrollbar.wheelReversed); // true or false

scrollbar.reverseWheel()

scrollbar.reverseWheel(reverse): void

| Param | Type | Description | | --- | :-: | --- | | reverse | boolean | true for reverse axis. |

Invert the axis of the wheel event.

scrollbar.reverseWheel(true);
console.log(scrollbar.reverseWheel); // true

scrollbar.update()

scrollbar.update(async?): void

| Param | Type | Description | | --- | :-: | --- | | async | boolean, optional | Force an asynchronous update. |

Forces scrollbar to update metrics.

By default, scrollbars are automatically updated with 100ms debounce (or childList changes if MutationObserver is supported). You can call this method to force an update when you modified contents inside scrollbar:

// append some contents to the scrollbar element...

// force an update
scrollbar.update();

// force an asynchronous update
scrollbar.update(true);

scrollbar.getSize()

scrollbar.getSize(): object

Return the size of scrollbar container element and scroll content element, it may be something like this:

{
    container: {
        width: 600,
        height: 400
    },
    content: {
        width: 1000,
        height: 3000
    }
}

scrollbar.setPosition()

scrollbar.setPosition(x, y): void

| Param | Type | Description | | --- | :-: | --- | | x | number | Scrolling offset in x-axis. | | y | number | Scrolling offset in y-axis. |

Likes the window.scrollTo() method, use this method to set the scrollbar to the given offset without easing:

// limit = { x: 500, y: 500 }
scrollbar.setPosition(100, 100);
console.log(scrollbar.offset); // { x: 100, y: 100 }

If the offset is out of limitation, it will be shrinked:

// limit = { x: 0, y: 100 }
scrollbar.setPosition(1024, 1024);
console.log(scrollbar.offset); // { x: 0, y: 100 }

scrollbar.scrollTo()

scrollbar.scrollTo(x, y, duration?, callback?): void

| Param | Type | Description | | --- | :-: | --- | | x | number | Scrolling offset in x-axis. | | y | number | Scrolling offset in y-axis. | | duration | number, optional | Easing duration, default is 0 (non-easing). | | callback | function, optional | Callback function that will be fired on the end of scrolling. |

Scrolls to given position with quadratic easing function:

scrollbar.scrollTo(100, 100, 300, function (scrollbar) {
    // ...
});

scrollbar.addListener()

scrollbar.addListener(listener): void

| Param | Type | Description | | --- | :-: | --- | | listener | (status) => void | Scrolling event listener. |

Since scrollbars will not fire a native scroll event, we need to registers thought scrollbar.addListener() method.

Notice: the callback functions will be invoked in every small scrolling, so be careful not to add time-consuming listeners that will slow down scrolling.

The status object contains following properties:

{
    direction: {
        // scrolling direction compares to the last offset
        x: 'none' | 'right' | 'left',
        y: 'none' | 'up' | 'down',
    },
    offset: {
        // current scrolling offset, equivalent to `scrollbar.offset`
        x: number,
        y: number,
    },
    limit: {
        // max-allowed scrolling distance, equivalent to `scrollbar.limit`
        x: number,
        y: number,
    }
}

scrollbar.scrollIntoView()

scrollbar.scrollIntoView(elem, options?): void

| Param | Type | Description | | --- | :-: | --- | | elem | Element | Target element. | | options | object, optional | Scrolling options, see the table below. |

| Property | type | default | description | | :-------: | :--: | :-----: | :---------- | | alignToTop | boolean | true | Whether to align to the top or the bottom edge of container. | | offsetTop | number | 0 | Offset to top edge of container (used only if alignToTop is true). | | offsetLeft | number | 0 | Offset to left edge of container. | | offsetBottom | number | 0 | Offset to bottom edge of container (used only if alignToTop is false). | | onlyScrollIfNeeded | boolean | false | Whether to scroll container when target element is visible. |

Scrolls the target element into visible area of scrollbar, like DOM method element.scrollIntoView(). This will be helpful when you want to create some anchors.

scrollbar.scrollIntoView(document.getElementById('a-section'), {
    offsetTop: 12,
    offsetLeft: 34,
    onlyScrollIfNeeded: true,
});

scrollbar.isVisible()

scrollbar.isVisible(elem): boolean

| Param | Type | Description | | --- | :-: | --- | | elem | Element | Target element. |

Checks if an element is visible in the current view area.

scrollbar.isVisible(document.getElementById('greet'))

scrollbar.infiniteScroll()

scrollbar.infiniteScroll(handler, threshold?): void

| Param | Type | Description | | --- | :-: | --- | | handler | (status) => void | Infinite scrolling handler. | | threshold | number, optional | Represents the trigger offset to the bottom edge of current scrollbar, default is 50. |

This is another useful method when you want to make infinite scrolling. Handlers will be invoked with the status object when you scrolling down over the given threshold:

instance.infiniteScroll(function (status) {
    // ...
}, 100);

scrollbar.stop()

scrollbar.stop(): void

Clears all pending movements and stops scrolling immediately.

// offset = { x: 0, y: 0 }
scrollbar.scrollTo(100, 100);
scrollbar.stop();

console.log(scrollbat.offset); // { x: 0, y: 0 }

scrollbar.destroy()

scrollbar.destroy(): void

Remove this scrollbar instance:

Before:

<section data-scrollbar style="overflow: hidden">
    <article class="scroll-content">
        ...
    </article>

    <aside class="scrollbar-track scrollbar-track-x">
        <div class="scrollbar-thumb scrollbar-thumb-x"></div>
    </aside>
    <aside class="scrollbar-track scrollbar-track-y">
        <div class="scrollbar-thumb scrollbar-thumb-y"></div>
    </aside>
</section>

After:

<section data-scrollbar>
    ...
</section>

Common mistakes

Initialize a scrollbar without a limited width or height

Likes the native scrollbars, a scrollable area means the content insides it is larger than the container itself, for example, a 500*500 area with a content which size is 1000*1000.

Therefore, it necessary to set the width or height for the container element:

#my-scrollbar {
    width: 500px;
    height: 500px;
    overflow: auto;
}

FAQ

How to listen to the scroll event?

Since scrollbars will not fire a native scroll event, we need to registers thought scrollbar.addListener() method:

scrollbar.addListener(function (status) {
    // ...
});

Related Projects

Contributing

  • Create an issue with an example on jsbin.com, including latest version of smooth-scrollbar through:

    <link rel="stylesheet" href="https://unpkg.com/smooth-scrollbar@latest/dist/smooth-scrollbar.css">
    
    <script src="https://unpkg.com/smooth-scrollbar@latest/dist/smooth-scrollbar.js"></script>
  • Run your forks locally with following steps:

    1. Clone the repo: git clone https://github.com/idiotWu/smooth-scrollbar.git,
    2. Install dependencies: npm run install,
    3. Start server: npm start.

Before making pull requests, make sure you have run npm test!

License

MIT.