jsScrollbar is a lightweight script (4K minified and gzipped) that enables you to override default system scrollbars on your website with beautiful, progressively-enhanced javascript scrollbars. It has no external dependencies, and can be included on any website, regardless of what other library you might be using. jsScrollbars are styled completely with CSS and can be customized to your heart's content.
You can download jsScrollbar here.
Initializing a new jsScrollbar
is a breeze. First you have
to set up some sort of container, which is usually just a div
with a set height, width, and maybe a border. Inside the container,
insert another div
with a class of .jssb-content
.
<div id="container"> <div class="jssb-content"> <!-- SCROLLING CONTENT GOES HERE --> </div> </div>
Once your content has loaded, just pass your container(s) to a jsScrollbar()
call in one of three ways: as a string of comma-separated
IDs, an HTMLElement
, or an array of HTMLElement
s.
// Comma separated IDs, pound sign optional jsScrollbar('container, #container2') // Element reference var el = document.getElementById('container'); jsScrollbar(el); // Array of elements through a jQuery call jsScrollbar( $('.container') );
jsScrollbar()
also takes a second optional argument for
preferences, but we'll get to that in a later section.
You can also save a reference of the returned jsScrollbar
and call its methods.
// Save a reference var sb = jsScrollbar('#container'); // Call methods sb.scrollTo(0, 120); sb.recalc();
There are a wide variety of CSS hooks available for styling your jsScrollbar
. For a detailed look at what exactly you need to do to setup
your CSS, take a look at the CSS files included. They are heavily commented and can
be used as a template for your own styles. A run down of useful hooks are detailed
below.
.jssb-applied
jsScrollbar()
upon a successful
initialization..jssb-scrollx
.jssb-scrolly
.jssb-focus
.jssb-content
.jssb-x
, .jssb-y
.jssb-x-left
, .jssb-x-right
, .jssb-y-up
, .jssb-y-down
.jssb-x-track
, .jssb-y-track
.jssb-x-thumb
, .jssb-y-thumb
jssb-x-*-click
, jssb-y-*-click
.jssb-y-thumb
element, it will receive an additional .jssb-y-thumb-click
class.In the default template, there are also a few nonessential classes for purely visual purposes that include:
.jssb-x-track-mid
, .jssb-x-track-end
, .jssb-y-track-mid
,
.jssb-y-track-end
.jssb-x-thumb-mid
, .jssb-x-thumb-end
, .jssb-y-thumb-mid
,
.jssb-y-thumb-end
Preferences are passed to a new jsScrollbar
as key-value
pairs. You can also override the default settings so you don't have to change the
preferences for each instance.
// Preferences are passed as the second argument jsScrollbar('#container', { horizontalScrolling: false, scrollSpeed: 20 }); // Or you can override the defaults jsScrollbar.defaults.horizontalScrolling = false; jsScrollbar.defaults.scrollSpeed = 20; jsScrollbar('#container');
A rundown of available preferences is listed below.
scrollSpeed
(Integer)scrollDistance
(Integer)wheelDistance
(Integer)tweenDuration
(Integer)tweenFn
(Function)An easing function. This function is passed a value between 0 and
1, representing the current position within the animation (0 = start,
0.5 = halfway, 1 = end). Modifying this value results in different kinds
of easing. Most easing equations out there are based off of Robert
Penner's work and are freely available, but you can also create your own
with a little trial and error and a graphing calculator. Once you plot
your function, anything between (0,0) and (1,1) is what will serve as
your animation. Setting this to null
will result
in a linear animation. The default easing function is:
function (pos) { return -Math.pow((pos-1), 4) + 1; }
disableTweening
(Boolean)horizontalScrolling
(Boolean)verticalScrolling
(Boolean)fixedThumb
(Boolean)template
(String)HTML to use when generating the scrollbar. The default is shown below.
<div class="jssb"> <div class="jssb-up"></div> <div class="jssb-track"> <div class="jssb-track-mid"></div> <div class="jssb-track-end"></div> <div class="jssb-thumb"> <div class="jssb-thumb-mid"></div> <div class="jssb-thumb-end"></div> </div> </div> <div class="jssb-down"></div> </div>
The template tries to be directionally unbiased (except for 'up' and 'down') so the axis is left out of the class name. Alternatively, you can also change this on a case by case basis by including it in the HTML of the container, but the elements must have their full class name with the axis. Decorative elements must keep the prefix of the element they decorate so the event handler know what they belong to.
The javascript powering jsScrollbar is fairly simplistic and will work in any remotely modern browser (including IE6). It's the CSS you use that might cause compatibility issues.
To easily prevent jsScrollbar
s from initializing, you can
set the .jssb-content
's overflow to
auto.
/* Use default system scrollbars */ .jssb-content { overflow: auto; ... } /* Enable jsScrollbars in capable browsers */ .jssb-applied > .jssb-content { overflow: hidden; ... }
All of the included demos use this technique to serve IE6 the default system scrollbars.
The demos included make extensive use of dimensions-by-positioning wherein declaring:
.jssb-y { position: absolute; top: 5px; bottom: 5px; }
would cause the vertical scrollbar to expand to the height of the container minus 5 pixels above and below it. This allows for scrollbars to easily expand to any size without having explicitly set dimensions for each scrollbar. IE6 does not support this. You could enable complete cross-browser compatibility by using hard coded dimensions, but you lose all flexibility.
Opera also displays some minor quirks when using this technique on a liquid container. It fails to resize the scrollbar when the size of the container changes. This, however, can be easily fixed by calling a javascript function that forces Opera to redraw the container and its children.
function forceOperaRedraw (sb) { if (!window.opera) return; if (!sb.length) sb = [sb]; var i = sb.length, o, r; while (i--) { o = sb[i].parent; if (o.offsetWidth > 0 && o.offsetHeight > 0) { o.style.display = 'none'; r = o.offsetHeight; o.style.display = ''; } } }
// Store instance of jsScrollbar var sb = jsScrollbar('#container'); //Force a redraw forceOperaRedraw(sb);
This particular function accepts a single jsScrollbar
instance or an array. It will do nothing in other browsers. See the included demos
for examples of its usage.
IE7 has issues with liquid containers in general. For some
reason, accessing an element's offset dimensions inside the container occasionally
causes IE to break rendering on the container. Sometimes this can be mitigated by
wrapping the recalc()
call in a setTimeout()
with 0 delay, but not always.
function recalcScrollbar () { setTimeout( function () { scrollbar.recalc(); }, 0 ); }
Of course, you can always just disable it entirely in IE7 like we do in IE6.
<!--[if lt IE 8]> <style type="text/css"> /* Disable jsScrollbar in IE7 */ .jssb-applied > .jssb-content { overflow: auto; } </style> <![endif]-->
jsScrollbar(container, [preferences])
jsScrollbar
instance or an array if called on multiple elements.jsScrollbar.scrollbars
jsScrollbars
.parent
jsScrollbar()
. If you modify this element beyond simple styles, you
will likely need to call recalc()
to avoid buggy
behavior.content
.jssb-content
element. As with
parent
, if you modify this element beyond simple styles,
you will likely need to call recalc()
afterwards.scrollTo(coordA, [coordB])
horizontalScrolling
or verticalScrolling
to
false. You can pass a null
value to ignore an
axis.scrollBy(distA, [distB])
scrollTo
, but with relative
distances instead of coordinates.tweenTo(coordA, [coordB])
scrollTo
, but with an animation.tweenBy(distA, [distB])
scrollBy
, but with an animation.disable()
enable()
jsScrollbar
.prefs(preference)
preference
is a string.prefs(preference, value)
prefs(preference_values)
jsScrollbar
.recalc()
jsScrollbar
. If
something goes wrong or is acting strange, calling this will probably fix it. For
example, if you modify the container element's innerHTML
,
the script would lose references to the scrollbar components. Calling
recalc()
would find the lost elements again. Also, if you
modify the content of the .jssb-content
or resize the
container, recalc()
would recalculate the thumb
size.jsScrollbars
s. It maintains history states, and is viewable without
javascript.jsScrollbar
is
applied to it.