Custom scrollbar
by Noir Noir
HTML
<div class="container js-scroller">
<p>text text text text text text text text tex t text text text text</p>
<p>text text text text text text text text text text text text text</p>
<p>text text text text text text text text text text text text text</p>
<div class="space-block"></div>
<p>text text text text text text text text text text text text text</p>
<div class="space-block"></div>
<p>text text text text text text text text text text text text text</p>
<p>text text text text text text text text text text text text text</p>
</div>
CSS
.container {
width: 300px;
height: 300px;
overflow: auto;
}
.container p {
margin: 0;
padding: 0;
margin-bottom: 5px;
}
.space-block {
height: 100px;
background: #cc0;
}
.js-scroller-container {
position: relative;
}
.js-scroller-native-scrollbar-hider {
position: relative;
overflow: hidden;
}
.js-scroller-scrollbar {
position: absolute;
top: 0;
right: 0;
bottom: 0;
height: 100%;
width: 5px;
opacity: 0.5;
transition: opacity 0.2s ease;
}
.js-scroller-container:hover .js-scroller-scrollbar {
opacity: 1;
}
.js-scroller-roller {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: #aaa;
}
.js-scroller-top-shadow,
.js-scroller-bottom-shadow {
position: absolute;
left: 0;
width: 100%;
height: 0;
background: none;
box-shadow: 0 0 40px 15px #fff;
}
.js-scroller-top-shadow {
top: 0;
}
.js-scroller-bottom-shadow {
bottom: 0;
}
JavaScript
var jsScroller = {
init: function(target) {
if (!jsScroller.isNeeded(target)) {
jsScroller.destroy(target);
return true;
}
jsScroller.buildHtml(target);
jsScroller.updateRoller(target);
jsScroller.updateShadows(target);
jsScroller.events(target);
},
buildHtml: function(target) {
var container = target.closest('.'+jsScroller.containerClass);
if (container.length) {
return true;
}
container = $('<div class="js-scroller-container"><div class="js-scroller-native-scrollbar-hider"></div><div class="js-scroller-scrollbar"><div class="js-scroller-roller"/></div></div></div>').appendTo(target.parent());
$('.js-scroller-native-scrollbar-hider', container).append(target).append('<div class="js-scroller-top-shadow"></div><div class="js-scroller-bottom-shadow">');
container.width('auto');
container.width(target.width());
},
destroy: function(target){
var container = target.closest('.js-scroller-container');
if (!container.length) {
return true;
}
$('.js-scroller-scrollbar', container).remove();
container.after(target);
container.remove();
},
events: function(target) {
var container = target.closest('.js-scroller-container');
if (!container.length || container.is('.js-events-attached')) {
return true;
}
target.on('scroll', function(){
jsScroller.updateRoller(target);
jsScroller.updateShadows(target);
});
container.addClass('js-events-attached');
},
updateRoller(target) {
var container = target.closest('.js-scroller-container'),
roller = $('.js-scroller-roller', container);
if (!roller.length) {
return false;
}
roller.height(jsScroller.getRollerHeight(target));
roller.css('top', jsScroller.getRollerPosition(target, roller));
},
updateShadows(target) {
var container = target.closest('.js-scroller-container'),
roller = $('.js-scroller-roller',...