Skip to content

Instantly share code, notes, and snippets.

@cowboy
Created February 27, 2011 18:54
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save cowboy/846423 to your computer and use it in GitHub Desktop.
Save cowboy/846423 to your computer and use it in GitHub Desktop.
jQuery Floating Scrollbar
/*!
* jQuery Floating Scrollbar - v0.4 - 02/28/2011
* http://benalman.com/
*
* Copyright (c) 2011 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($){
var // A few reused jQuery objects.
win = $(this),
html = $('html'),
// All the elements being monitored.
elems = $([]),
// The current element.
current,
// The previous current element.
previous,
// Create the floating scrollbar.
scroller = $('<div id="floating-scrollbar"><div/></div>'),
scrollerInner = scroller.children();
// Initialize the floating scrollbar.
scroller
.hide()
.css({
position: 'fixed',
bottom: 0,
height: '30px',
overflowX: 'auto',
overflowY: 'hidden'
})
.scroll(function() {
// If there's a current element, set its scroll appropriately.
current && current.scrollLeft(scroller.scrollLeft())
});
scrollerInner.css({
border: '1px solid #fff',
opacity: 0.01
});
// Call on elements to monitor their position and scrollness. Pass `false` to
// stop monitoring those elements.
$.fn.floatingScrollbar = function( state ) {
if ( state === false ) {
// Remove these elements from the list.
elems = elems.not(this);
// Stop monitoring elements for scroll.
this.unbind('scroll', scrollCurrent);
if ( !elems.length ) {
// No elements remain, so detach scroller and unbind events.
scroller.detach();
win.unbind('resize scroll', update);
}
} else if ( this.length ) {
// Don't assume the set is non-empty!
if ( !elems.length ) {
// Adding elements for the first time, so bind events.
win.resize(update).scroll(update);
}
// Add these elements to the list.
elems = elems.add(this);
}
// Update.
update();
// Make chainable.
return this;
};
// Call this to force an update, for instance, if elements were inserted into
// the DOM before monitored elements, changing their vertical position.
$.floatingScrollbarUpdate = update;
// Hide or show the floating scrollbar.
function setState( state ) {
scroller.toggle(!!state);
}
// Sync floating scrollbar if element content is scrolled.
function scrollCurrent() {
current && scroller.scrollLeft(current.scrollLeft())
}
// This is called on window scroll or resize, or when elements are added or
// removed from the internal elems list.
function update() {
previous = current;
current = null;
// Find the first element whose content is visible, but whose bottom is
// below the viewport.
elems.each(function(){
var elem = $(this),
top = elem.offset().top,
bottom = top + elem.height(),
viewportBottom = win.scrollTop() + win.height(),
topOffset = 30;
if ( top + topOffset < viewportBottom && bottom > viewportBottom ) {
current = elem;
return false;
}
});
// Abort if no elements were found.
if ( !current ) { setState(); return; }
// Test to see if the current element has a scrollbar.
var scroll = current.scrollLeft(),
scrollMax = current.scrollLeft(90019001).scrollLeft(),
widthOuter = current.innerWidth(),
widthInner = widthOuter + scrollMax;
current.scrollLeft(scroll);
// Abort if the element doesn't have a scrollbar.
if ( widthInner <= widthOuter ) { setState(); return; }
// Show the floating scrollbar.
setState(true);
// Sync floating scrollbar if element content is scrolled.
if ( !previous || previous[0] !== current[0] ) {
previous && previous.unbind('scroll', scrollCurrent);
current.scroll(scrollCurrent).after(scroller);
}
// Adjust the floating scrollbar as-necessary.
scroller
.css({
left: current.offset().left - win.scrollLeft(),
width: widthOuter
})
.scrollLeft(scroll);
scrollerInner.width(widthInner);
}
})(jQuery);
/*
* jQuery Floating Scrollbar - v0.4 - 02/28/2011
* http://benalman.com/
*
* Copyright (c) 2011 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function(a){function k(){f=e,e=null,d.each(function(){var c=a(this),d=c.offset().top,f=d+c.height(),g=b.scrollTop()+b.height(),h=30;if(d+h<g&&f>g){e=c;return!1}});if(!e)i();else{var c=e.scrollLeft(),k=e.scrollLeft(90019001).scrollLeft(),l=e.innerWidth(),m=l+k;e.scrollLeft(c);if(m<=l){i();return}i(!0);if(!f||f[0]!==e[0])f&&f.unbind("scroll",j),e.scroll(j).after(g);g.css({left:e.offset().left-b.scrollLeft(),width:l}).scrollLeft(c),h.width(m)}}function j(){e&&g.scrollLeft(e.scrollLeft())}function i(a){g.toggle(!!a)}var b=a(this),c=a("html"),d=a([]),e,f,g=a('<div id="floating-scrollbar"><div/></div>'),h=g.children();g.hide().css({position:"fixed",bottom:0,height:"30px",overflowX:"auto",overflowY:"hidden"}).scroll(function(){e&&e.scrollLeft(g.scrollLeft())}),h.css({border:"1px solid #fff",opacity:.01}),a.fn.floatingScrollbar=function(a){a===!1?(d=d.not(this),this.unbind("scroll",j),d.length||(g.detach(),b.unbind("resize scroll",k))):this.length&&(d.length||b.resize(k).scroll(k),d=d.add(this)),k();return this},a.floatingScrollbarUpdate=k})(jQuery)
@cowboy
Copy link
Author

cowboy commented Feb 27, 2011

See an example.

@jcgonzave
Copy link

hello cowboy
It doesn't work when I put the page inside an iframe
Can you tell me please, what should I do?

@kflorence
Copy link

@dtvuong
Copy link

dtvuong commented Feb 5, 2015

I want to use it in mysite on IE8, but it's not work. Can you help me.

@swaprks
Copy link

swaprks commented Sep 8, 2015

Hi,
I found the flickering issue with IE9 and it was related to the scrollLeft. I have fixed and added the code here.

https://github.com/swaprks/jQuery-floating-scrollbar-/blob/master/jquery.ba-floatingscrollbar.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment