jQuery custom content scroller
Highly customizable custom scrollbar jQuery plugin. Features include vertical and/or horizontal scrollbar(s), adjustable scrolling momentum, mouse-wheel (via jQuery mousewheel plugin), keyboard and touch support, ready-to-use themes and customization via CSS, RTL direction support, option parameters for full control of scrollbar functionality, methods for triggering actions like scroll-to, update, destroy etc., user-defined callbacks and more.
Current version 3.1.5 (Changelog)
Upgrading from version 2
How to use it
Get started by downloading the archive which contains the plugin files (and a large amount of HTML demos and examples). Extract and upload jquery.mCustomScrollbar.concat.min.js, jquery.mCustomScrollbar.css and mCSB_buttons.png to your web server (alternatively you can load plugin files from a CDN).
HTML
Include jquery.mCustomScrollbar.css in the head tag your HTML document (more info)
<link rel="stylesheet" href="/path/to/jquery.mCustomScrollbar.css" />
Include jQuery library (if your project doesn’t use it already) and jquery.mCustomScrollbar.concat.min.js in the head tag or at the very bottom of your document, just before the closing body tag
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="/path/to/jquery.mCustomScrollbar.concat.min.js"></script>
CSS
The element(s) you want to add scrollbar(s) should have the typical CSS properties of an overflowed block which are a height (or max-height) value, an overflow value of auto (or hidden) and content long enough to require scrolling. For horizontal scrollbar, the element should have a width (or max-width) value set.
If you prefer to set your element’s height/width via javascript, you can use the setHeight
/setWidth
option parameters.
Initialization
Initialize via javascript
After files inclusion, call mCustomScrollbar function on the element selector you want to add the scrollbar(s)
<script> (function($){ $(window).on("load",function(){ $(".content").mCustomScrollbar(); }); })(jQuery); </script>
Initialize via HTML
Add the class mCustomScrollbar
to any element you want to add custom scrollbar(s) with default options. Optionally, set its axis via the HTML data attribute data-mcs-axis
(e.g. "x"
for horizontal and "y"
for vertical) and its theme via data-mcs-theme
. For example:
<div class="mCustomScrollbar" data-mcs-theme="dark"> <!-- your content --> </div>
Basic configuration & option parameters
axis
By default, the script applies a vertical scrollbar. To add a horizontal or 2-axis scrollbars, invoke mCustomScrollbar function with the axis option set to "x"
or "yx"
respectively
$(".content").mCustomScrollbar({ axis:"x" // horizontal scrollbar });
$(".content").mCustomScrollbar({ axis:"yx" // vertical and horizontal scrollbar });
theme
To quickly change the appearance of the scrollbar, set the theme option parameter to any of the ready-to-use themes available in jquery.mCustomScrollbar.css, for example:
$(".content").mCustomScrollbar({ theme:"dark" });
Configuration
You can configure your scrollbar(s) using the following option parameters on mCustomScrollbar function
Usage $(selector).mCustomScrollbar({ option: value });
setWidth: false
- Set the width of your content (overwrites CSS width), value in pixels (integer) or percentage (string).
setHeight: false
- Set the height of your content (overwrites CSS height), value in pixels (integer) or percentage (string).
setTop: 0
- Set the initial css top property of content, accepts string values (css top position).
Example:setTop: "-100px"
.
setLeft: 0
- Set the initial css left property of content, accepts string values (css left position).
Example:setLeft: "-100px"
.
axis: "string"
- Define content’s scrolling axis (the type of scrollbars added to the element: vertical and/of horizontal).
Available values:"y"
,"x"
,"yx"
.axis: "y"
– vertical scrollbar (default)axis: "x"
– horizontal scrollbaraxis: "yx"
– vertical and horizontal scrollbars
scrollbarPosition: "string"
- Set the position of scrollbar in relation to content.
Available values:"inside"
,"outside"
.
SettingscrollbarPosition: "inside"
(default) makes scrollbar appear inside the element. SettingscrollbarPosition: "outside"
makes scrollbar appear outside the element. Note that setting the value to"outside"
requires your element (or parent elements) to have CSSposition: relative
(otherwise the scrollbar will be positioned in relation to document’s root element).
scrollInertia: integer
- Set the amount of scrolling momentum as animation duration in milliseconds.
Higher value equals greater scrolling momentum which translates to smoother/more progressive animation. Set to0
to disable.
autoDraggerLength: boolean
- Enable or disable auto-adjusting scrollbar dragger length in relation to scrolling amount (same bahavior with browser’s native scrollbar).
SetautoDraggerLength: false
when you want your scrollbar to (always) have a fixed size.
autoHideScrollbar: boolean
- Enable or disable auto-hiding the scrollbar when inactive.
SettingautoHideScrollbar: true
will hide the scrollbar(s) when scrolling is idle and/or cursor is out of the scrolling area.
Please note that some special themes like “minimal” overwrite this option.
autoExpandScrollbar: boolean
- Enable or disable auto-expanding the scrollbar when cursor is over or dragging the scrollbar.
alwaysShowScrollbar: integer
- Always keep scrollbar(s) visible, even when there’s nothing to scroll.
alwaysShowScrollbar: 0
– disable (default)alwaysShowScrollbar: 1
– keep dragger rail visiblealwaysShowScrollbar: 2
– keep all scrollbar components (dragger, rail, buttons etc.) visible
snapAmount: integer
- Make scrolling snap to a multiple of a fixed number of pixels. Useful in cases like scrolling tabular data, image thumbnails or slides and you need to prevent scrolling from stopping half-way your elements. Note that your elements must be of equal width or height in order for this to work properly.
To set different values for vertical and horizontal scrolling, use an array:[y,x]
snapOffset: integer
- Set an offset (in pixels) for the snapAmount option. Useful when for example you need to offset the snap amount of table rows by the table header.
mouseWheel:{ enable: boolean }
- Enable or disable content scrolling via mouse-wheel.
mouseWheel:{ scrollAmount: integer }
- Set the mouse-wheel scrolling amount (in pixels). The default value
"auto"
adjusts scrolling amount according to scrollable content length.
mouseWheel:{ axis: "string" }
- Define the mouse-wheel scrolling axis when both vertical and horizontal scrollbars are present.
Setaxis: "y"
(default) for vertical oraxis: "x"
for horizontal scrolling.
mouseWheel:{ preventDefault: boolean }
- Prevent the default behaviour which automatically scrolls the parent element when end or beginning of scrolling is reached (same bahavior with browser’s native scrollbar).
mouseWheel:{ deltaFactor: integer }
- Set the number of pixels one wheel notch scrolls. The default value “auto” uses the OS/browser value.
mouseWheel:{ normalizeDelta: boolean }
- Enable or disable mouse-wheel (delta) acceleration. Setting
normalizeDelta: true
translates mouse-wheel delta value to -1 or 1.
mouseWheel:{ invert: boolean }
- Invert mouse-wheel scrolling direction. Set to
true
to scroll down or right when mouse-wheel is turned upwards.
mouseWheel:{ disableOver: [array] }
- Set the tags that disable mouse-wheel when cursor is over them.
Default value:["select","option","keygen","datalist","textarea"]
scrollButtons:{ enable: boolean }
- Enable or disable scrollbar buttons.
scrollButtons:{ scrollAmount: integer }
- Set the buttons scrolling amount (in pixels). The default value
"auto"
adjusts scrolling amount according to scrollable content length.
scrollButtons:{ scrollType: "string" }
- Define the buttons scrolling type/behavior.
scrollType: "stepless"
– continuously scroll content while pressing the button (default)scrollType: "stepped"
– each button click scrolls content by a certain amount (defined in scrollAmount option above)
scrollButtons:{ tabindex: integer }
- Set a tabindex value for the buttons.
keyboard:{ enable: boolean }
- Enable or disable content scrolling via the keyboard.
The plugin supports the directional arrows (top, left, right and down), page-up (PgUp), page-down (PgDn), Home and End keys.
keyboard:{ scrollAmount: integer }
- Set the keyboard arrows scrolling amount (in pixels). The default value
"auto"
adjusts scrolling amount according to scrollable content length.
keyboard:{ scrollType: "string" }
- Define the keyboard arrows scrolling type/behavior.
scrollType: "stepless"
– continuously scroll content while pressing the arrow key (default)scrollType: "stepped"
– each key release scrolls content by a certain amount (defined in scrollAmount option above)
contentTouchScroll: integer
- Enable or disable content touch-swipe scrolling for touch-enabled devices.
To completely disable, setcontentTouchScroll: false
.
Integer values define the axis-specific minimum amount required for scrolling momentum (default:25
).
documentTouchScroll: boolean
- Enable or disable document touch-swipe scrolling for touch-enabled devices.
advanced:{ autoExpandHorizontalScroll: boolean }
- Auto-expand content horizontally (for
"x"
or"yx"
axis).
If set totrue
, content will expand horizontally to accommodate any floated/inline-block elements.
Setting its value to2
(integer) forces the non scrollHeight/scrollWidth method. A value of3
forces the scrollHeight/scrollWidth method.
advanced:{ autoScrollOnFocus: "string" }
- Set the list of elements/selectors that will auto-scroll content to their position when focused.
For example, when pressing TAB key to focus input fields, if the field is out of the viewable area the content will scroll to its top/left position (same bahavior with browser’s native scrollbar).
To completely disable this functionality, setautoScrollOnFocus: false
.
Default:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']"
advanced:{ updateOnContentResize: boolean }
- Update scrollbar(s) automatically on content, element or viewport resize.
The value should betrue
(default) for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements etc.
advanced:{ updateOnImageLoad: boolean }
- Update scrollbar(s) automatically each time an image inside the element is fully loaded.
Default value isauto
which triggers the function only on"x"
and"yx"
axis (if needed).
The value should betrue
when your content contains images and you need the function to trigger on any axis.
advanced:{ updateOnSelectorChange: "string" }
- Update scrollbar(s) automatically when the amount and size of specific selectors changes.
Useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size.
For example, settingupdateOnSelectorChange: "ul li"
will update scrollbars each time list-items inside the element are changed.
Setting the value totrue
, will update scrollbars each time any element is changed.
To disable (default) set tofalse
.
advanced:{ extraDraggableSelectors: "string" }
- Add extra selector(s) that’ll release scrollbar dragging upon mouseup, pointerup, touchend etc.
Example:extraDraggableSelectors: ".myClass, #myID"
advanced:{ releaseDraggableSelectors: "string" }
- Add extra selector(s) that’ll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc.
Example:releaseDraggableSelectors: ".myClass, #myID"
advanced:{ autoUpdateTimeout: integer }
- Set the auto-update timeout in milliseconds.
Default timeout:60
theme: "string"
- Set the scrollbar theme.
View all ready-to-use themes
All themes are contained in plugin’s CSS file (jquery.mCustomScrollbar.css).
Default theme:"light"
callbacks:{ onCreate: function(){} }
- A function to call when plugin markup is created.
Example:
callbacks:{ onCreate:function(){ console.log("Plugin markup generated"); } }
callbacks:{ onInit: function(){} }
- A function to call when scrollbars have initialized (demo).
Example:
callbacks:{ onInit:function(){ console.log("Scrollbars initialized"); } }
callbacks:{ onScrollStart: function(){} }
- A function to call when scrolling starts (demo).
Example:
callbacks:{ onScrollStart:function(){ console.log("Scrolling started..."); } }
callbacks:{ onScroll: function(){} }
- A function to call when scrolling is completed (demo).
Example:
callbacks:{ onScroll:function(){ console.log("Content scrolled..."); } }
callbacks:{ whileScrolling: function(){} }
- A function to call while scrolling is active (demo).
Example:
callbacks:{ whileScrolling:function(){ console.log("Scrolling..."); } }
callbacks:{ onTotalScroll: function(){} }
- A function to call when scrolling is completed and content is scrolled all the way to the end (bottom/right) (demo).
Example:
callbacks:{ onTotalScroll:function(){ console.log("Scrolled to end of content."); } }
callbacks:{ onTotalScrollBack: function(){} }
- A function to call when scrolling is completed and content is scrolled back to the beginning (top/left) (demo).
Example:
callbacks:{ onTotalScrollBack:function(){ console.log("Scrolled back to the beginning of content."); } }
callbacks:{ onTotalScrollOffset: integer }
- Set an offset for the onTotalScroll option.
For example, settingonTotalScrollOffset: 100
will trigger the onTotalScroll callback 100 pixels before the end of scrolling is reached.
callbacks:{ onTotalScrollBackOffset: integer }
- Set an offset for the onTotalScrollBack option.
For example, settingonTotalScrollBackOffset: 100
will trigger the onTotalScrollBack callback 100 pixels before the beginning of scrolling is reached.
callbacks:{ alwaysTriggerOffsets: boolean }
- Set the behavior of calling onTotalScroll and onTotalScrollBack offsets.
By default, callback offsets will trigger repeatedly while content is scrolling within the offsets.
SetalwaysTriggerOffsets: false
when you need to trigger onTotalScroll and onTotalScrollBack callbacks once, each time scroll end or beginning is reached.
callbacks:{ onOverflowY: function(){} }
- A function to call when content becomes long enough and vertical scrollbar is added.
Example:
callbacks:{ onOverflowY:function(){ console.log("Vertical scrolling required"); } }
callbacks:{ onOverflowX: function(){} }
- A function to call when content becomes wide enough and horizontal scrollbar is added.
Example:
callbacks:{ onOverflowX:function(){ console.log("Horizontal scrolling required"); } }
callbacks:{ onOverflowYNone: function(){} }
- A function to call when content becomes short enough and vertical scrollbar is removed.
Example:
callbacks:{ onOverflowYNone:function(){ console.log("Vertical scrolling is not required"); } }
callbacks:{ onOverflowXNone: function(){} }
- A function to call when content becomes narrow enough and horizontal scrollbar is removed.
Example:
callbacks:{ onOverflowXNone:function(){ console.log("Horizontal scrolling is not required"); } }
callbacks:{ onBeforeUpdate: function(){} }
- A function to call right before scrollbar(s) are updated.
Example:
callbacks:{ onBeforeUpdate:function(){ console.log("Scrollbars will update"); } }
callbacks:{ onUpdate: function(){} }
- A function to call when scrollbar(s) are updated.
Example:
callbacks:{ onUpdate:function(){ console.log("Scrollbars updated"); } }
callbacks:{ onImageLoad: function(){} }
- A function to call each time an image inside the element is fully loaded and scrollbar(s) are updated.
Example:
callbacks:{ onImageLoad:function(){ console.log("Image loaded"); } }
callbacks:{ onSelectorChange: function(){} }
- A function to call each time a type of element is added, removed or changes its size and scrollbar(s) are updated.
Example:
callbacks:{ onSelectorChange:function(){ console.log("Scrollbars updated"); } }
live: "string"
- Enable or disable applying scrollbar(s) on all elements matching the current selector, now and in the future.
Setlive: true
when you need to add scrollbar(s) on elements that do not yet exist in the page. These could be elements added by other scripts or plugins after some action by the user takes place (e.g. lightbox markup may not exist untill the user clicks a link).
If you need at any time to disable or enable the live option, setlive: "off"
and"on"
respectively.
You can also tell the script to disable live option after the first invocation by settinglive: "once"
.
liveSelector: "string"
- Set the matching set of elements (instead of the current selector) to add scrollbar(s), now and in the future.
Plugin methods
Ways to execute various plugin actions programmatically from within your script(s).
update
Usage $(selector).mCustomScrollbar("update");
Call the update method to manually update existing scrollbars to accommodate new content or resized element(s). This method is by default called automatically by the script (via updateOnContentResize
option) when the element itself, its content or scrollbar size changes.
scrollTo
Usage $(selector).mCustomScrollbar("scrollTo",position,options);
Call the scrollTo method to programmatically scroll the content to the position parameter (demo).
position parameter
Position parameter can be:
"string"
- e.g. element selector:
"#element-id"
- e.g. special pre-defined position:
"bottom"
- e.g. number of pixels less/more:
"-=100"
/"+=100"
- e.g. element selector:
integer
- e.g. number of pixels:
100
- e.g. number of pixels:
[array]
- e.g. different y/x position:
[100,50]
- e.g. different y/x position:
object/function
- e.g. jQuery object:
$("#element-id")
- e.g. js object:
document.getelementbyid("element-id")
- e.g. function:
function(){ return 100; }
- e.g. jQuery object:
Pre-defined position strings:
"bottom"
– scroll to bottom"top"
– scroll to top"right"
– scroll to right"left"
– scroll to left"first"
– scroll to the position of the first element within content"last"
– scroll to the position of the last element within content
Method options
scrollInertia: integer
- Scroll-to duration, value in milliseconds.
Example:
$(selector).mCustomScrollbar("scrollTo","bottom",{ scrollInertia:3000 });
scrollEasing: "string"
- Scroll-to animation easing, values:
"linear"
,"easeOut"
,"easeInOut"
.
Example:
$(selector).mCustomScrollbar("scrollTo","bottom",{ scrollEasing:"easeOut" });
moveDragger: boolean
- Scroll scrollbar dragger (instead of content).
Example:
$(selector).mCustomScrollbar("scrollTo",80,{ moveDragger:true });
timeout: integer
- Set a timeout for the method (the default timeout is 60 ms in order to work with automatic scrollbar update), value in milliseconds.
Example:
$(selector).mCustomScrollbar("scrollTo","top",{ timeout:1000 });
callbacks: boolean
- Trigger user defined callbacks after scroll-to completes.
Example:
$(selector).mCustomScrollbar("scrollTo","left",{ callbacks:false });
stop
Usage $(selector).mCustomScrollbar("stop");
Stops any running scrolling animations (usefull when you wish to interupt a previously scrollTo method call).
disable
Usage $(selector).mCustomScrollbar("disable");
Calling disable method will temporarily disable the scrollbar (demo). Disabled scrollbars can be re-enable by calling the update method.
To disable the scrollbar and reset its content position, set the method’s reset parameter to true
$(selector).mCustomScrollbar("disable",true);
destroy
Usage $(selector).mCustomScrollbar("destroy");
Calling destroy method will completely remove the custom scrollbar and return the element to its original state (demo).
Scrollbar styling & themes
You can design and visually customize your scrollbars with pure CSS, using jquery.mCustomScrollbar.css which contains the default/basic styling and all scrollbar themes.
The easiest/quickest way is to select a ready-to-use scrollbar theme. For example:
$(selector).mCustomScrollbar({ theme:"dark" });
You can modify the default styling or any theme either directly in jquery.mCustomScrollbar.css or by overwriting the CSS rules in another stylesheet.
Creating a new scrollbar theme
Create a name for your theme (e.g. “my-theme”) and set it as the value of the theme option
$(selector).mCustomScrollbar({ theme:"my-theme" });
Your element will get the class “mCS-my-theme” (your theme-name with “mCS” prefix), so you can create your CSS using the .mCS-my-theme
in your rules. For instance:
.mCS-my-theme.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: red; } .mCS-my-theme.mCSB_scrollTools .mCSB_draggerRail{ background-color: white; } /* and so on... */
In the same manner you can clone any existing theme (e.g. “dark”), change its selector (e.g. .mCS-dark
) to your own theme name (e.g. .mCS-my-theme
) and modify its CSS rules.
Scrollbar markup
The plugin applies specific id (unique) and/or classes to every scrollbar element/component, meaning that you can target and modify any scrollbar in more than one ways.
For example, every element with a scrollbar gets a unique class in the form of _mCS_1
, _mCS_2
etc. Every scrollbar container element gets a unique id in the form of mCSB_1_scrollbar_vertical
, mCSB_2_scrollbar_vertical
etc. Every scrollbar dragger gets a unique id in the form of mCSB_1_dragger_vertical
, mCSB_2_dragger_vertical
etc. in addition to the class mCSB_dragger
. All these mean that you can do stuff like:
._mCS_1 .mCSB_dragger .mCSB_dragger_bar{ background-color: red; } ._mCS_2 .mCSB_dragger .mCSB_dragger_bar{ background-color: green; } #mCSB_3_dragger_vertical .mCSB_dragger_bar{ background-color: blue; } #mCSB_1_scrollbar_vertical .mCSB_dragger{ height: 100px; } #mCSB_1_scrollbar_horizontal .mCSB_dragger{ width: 100px; } .mCSB_1_scrollbar .mCSB_dragger .mCSB_draggerRail{ width: 4px; }
User-defined callbacks
You can trigger your own js function(s) by calling them inside mCustomScrollbar callbacks option parameter
$(".content").mCustomScrollbar({ callbacks:{ onScroll:function(){ myCustomFn(this); } } }); function myCustomFn(el){ console.log(el.mcs.top); }
In the example above, each time a scroll event ends and content has stopped scrolling, the content’s top position will be logged in browser’s console. There are available callbacks for each step of the scrolling event:
onScrollStart
– triggers the moment a scroll event startswhileScrolling
– triggers while scroll event is runningonScroll
– triggers when a scroll event completesonTotalScroll
– triggers when content has scrolled all the way to bottom or rightonTotalScrollBack
– triggers when content has scrolled all the way back to top or left
You can set an offset value (pixels) for both onTotalScroll
and onTotalScrollBack
by setting onTotalScrollOffset
and onTotalScrollBackOffset
respectively (view example).
By default, onTotalScroll
and onTotalScrollBack
callbacks are triggered repeatedly. To prevent multiple calls when content is within their offset, set alwaysTriggerOffsets
option to false
(view example).
Additional callbacks:
onInit
onOverflowY
onOverflowX
onOverflowYNone
onOverflowXNone
onUpdate
onImageLoad
onSelectorChange
Returning values
The script returns a number of values and objects related to scrollbar that you can use in your own functions
this
– the original element containing the scrollbar(s)this.mcs.content
– the original content wrapper as jquery objectthis.mcs.top
– content’s top position (pixels)this.mcs.left
– content’s left position (pixels)this.mcs.draggerTop
– scrollbar dragger’s top position (pixels)this.mcs.draggerLeft
– scrollbar dragger’s left position (pixels)this.mcs.topPct
– content vertical scrolling percentagethis.mcs.leftPct
– content horizontal scrolling percentagethis.mcs.direction
– content’s scrolling direction (y or x)
Plugin-specific jQuery expressions
$("#myID:mcsInView")
- Select element(s) in your content that are within scrollable viewport.
As condition:$("#myID").is(":mcsInView");
$(".content:mcsOverflow")
- Select overflowed element(s) with visible scrollbar.
As condition:$(".content").is(":mcsOverflow");
$("#myID:mcsInSight")
$("#myID:mcsInSight(exact)")
- Select element(s) in your content that are in view of the scrollable viewport. Using the
exact
parameter will include elements that have any part of them (even 1 pixel) in view of the scrollable viewport.
As condition:$("#myID").is(":mcsInSight");
,$("#myID").is(":mcsInSight(exact)");
Plugin dependencies & requirements
- jQuery version 1.6.0 or higher
- Mouse-wheel support
License
This work is released under the MIT License.
You are free to use, study, improve and modify it wherever and however you like.
https://opensource.org/licenses/MIT
Donating helps greatly in developing and updating free software and running this blog π
Hi,
It is possible to set horizontal and vertical scroll at same time. Would you please provide a sample for horizontal and vertical scroll bar at same time.
Thanks & Regards,
Sanil Shinde.
I really love this scroll bar. there is so many of them on the web that are really bad lol. I’m going to come back later in a few months and make a donation.
Is there no way to control the speed of scroll to?
Not really. It scrolls to position instantly.
Hi malihu, amazing blog this is! π
I tried the plugin, it appears but doesn’t scroll down. The console shows this error,
‘Uncaught TypeError: Object [object Object] has no method ‘draggable’ ‘
refering to the line no. 296 in the jquery.mCustomScrollbar.js
can you please clarify this?
also, the scroll bar doesn’t disappear when the content is not long enough.
i haven’t changed a thing in the code i forked from git.
i just started using this plug in too. I had some issues. make sure you are using jquery 1.8 and jquery UI 1.8.24
Hello again,
I include in the html document, the jquery-ui-1.8.21.custom.min.js file, and now the scroll is working. But the length of the scroll is fixed.
http://www.saarang.org/2013/site/main2/#hospitality_page
Please check this link for seeing what i’m referring to.
The site is under development still, so please excuse any malfunctions. Please do suggest any improvements that you feel, we’ll all be very happy to incorporate them.
Cheers!
nice plugin
Hi. Another doubt: It’s possible to have the dragger rail (and obviously all the scroll functionality) restricted to a size smaller than the content? I mean, using horizontal version, imagine a gallery filling the full screen width, but scrollbar (rail+dragger) only filling a fixed size, like 400px.
Thanks in advance.
Yes of course. For horizontal scrollbar, set .mCSB_scrollTools css width to what you need. For example, adding the following rules will make your horizontal scrollbar 400 pixels wide and horizontally centered:
.mCSB_horizontal.mCustomScrollBox .mCSB_scrollTools{ width:400px; left:50%; margin-left:-200px; }
Hello malihu:
It’ a great plugin, I have a problem but i don’t know if the thing that i try to made it’s possible, i try to put the two scrollbars on the same div, horizontal and vertical, is it possible??
If is possible can you help me?, thanks
Hi Juan. Check question 41. π
Thanks perLover, i’m going to try another option, if i solve my problem, i’ll post how i have solved it, sorry for my written, i don’t have a good english
Hi. Wonderfull plugin.
One small doubt. I’m trying to place the whole scrollbar on top (using horizontal configuration).
I’m placing the .mCSB_scrollTools with css() on top:0px (i can’t use negative values, as it’s insde the wrapper). After that i’ve move the images_container to top:20px.
My problem is that event when i setup a set_height config parameter 20px more than images, they look cutted on bottom (those 20px).
Can you point me in the right direction?
Thanks a bunch.
Ok, don’t worry, i solved, styling the .mCSB_container object directly.
Thanks again for such a fantastic plugin. I’ll make a donation once the project finished and charged.
Seems like there is a problem in this situation: I have 2 tabs. When the user clicks one tab, the only container that uses your script receives content related to this tab. When the other tab is clicked, content is cleared and replaced with another set of content. Of course Update is called each time to refresh the scrollbar.
Because the scrollbar may not be at the top position when I click on the second tab, I also call ScrollTo “top” after setting the new content. The problem appears when the new content is small and there is no need of a scrollbar. Update correctly removes the scrollbar but then calling ScrollTo “top” makes the content disappear (I checked with firebug and in fact it has been scrolled out of and above the window).
Any idea?
Without knowing exactly what your code is like, you could add a simple condition for calling scrollTo (e.g. scroll to top only if scrollbar does exist):
if(!$(".content .mCSB_container").is(".mCS_no_scrollbar")){ $(".content").mCustomScrollbar("scrollTo","top"); }
Thanks. This is actually what I did already since I noticed that when setting new content and calling update, the scrollbar aws not there anymore and the content was correctly scrolled on top.
I can’t show you my long code, but in pseudo code it is:
– $(“.content .mCSB_container”).empty()
– append some new content inside $(“.content .mCSB_container”)
– call Update
– call ScrollTo
There may be a bug in your ScroollTo code when there is no scrollbar?
If you completely replace the content (e.g. via .empty() and .append()) you don’t really need calling the scrollTo method after. Try inserting scrollTo at the top before emptying your content. If you could sent me your file(s) via e-mail I believe I could help much better.
Hello!
Awesome plugin, by the way, and it works great everywhere in my page EXCEPT….
…when I try to use it in conjunction with ColorBox (a modal box/lightbox plugin).
What happens is, if I click on the link that makes the ColorBox pop up right before everything loads on page, it appears that the scrollbar script STARTS working, but either doesn’t form the scrollbar (but starts to form the content box), or it loads properly, but won’t work again if I wait for everything on the page to load before clicking on the link to make ColorBox pop up.
I am not really stealth with jQuery/script, so debugging is a bit of a nightmare for me. I have to use all these different plugins to give the client their desired results, but I’m afraid there are conflicts I’m not sure how to fix. But when I temporarily turn off the other plugins, the scrollbar still doesn’t work properly in ColorBox.
Halp? π
http://www.brittondev.com/colwell/index2.html
Click on ‘Contact Us’ in the footer menu, bottom right. This is what I’m using to develop for my other pop up boxes.
Thank you so much!
Erin
Hi,
It seems that you apply the custom scrollbar on the .scrollit_footer element which ColorBox script adds and removes dynamically. This element is added only when you click your footer link and it’s completely removed when clicking the close icon.
You can try calling
$(".scrollit_footer").mCustomScrollbar()
inside the onOpen callback of colorbox function (instead of window load).Another way would be to apply the scrollbar on .cboxContent (or some other element that does always exist in your markup) and probably call the update method in the onOpen callback.
Hi,
It’s awesome.
I have some issues:
1. Whenever i try it with my slideUp(); and slideDown(); content it doesn’t create any scrollbar
2. scrollTo.. anchor tag smooth scrolling doesn’t work with it.
Please help!
Many thanks,
Mufeed Ahmad
Hi,
You need to call plugin’s update method as a callback to your slideDown function (see “Hiding & showing content blocks with custom scrollbars” for more info). For example:
$(".content").slideDown("slow",function(){ $(this).mCustomScrollbar("update"); });
Everything in this plugin is working except Easing. I am using the lastest download with jQuery 1.8.2 and your custom jquery-ui-1.8.23.custom.min.js file.
scrollTo has no easing, as well as mousewheel or continuous scrolling.
Seems to be related to this in the scroll function:
if($.browser.webkit){ /*fix webkit zoom and jquery animate*/
var screenCssPixelRatio=(window.outerWidth-8)/window.innerWidth,
isZoomed=(screenCssPixelRatio1.02);
}
then the next line checks for it
if($this.data(“scrollInertia”)===0 || isZoomed)
and no animate method is called. Why would you have this check for Chrome ? Removing it makes it work. Any reason this would be?
Because when Chrome browser is zoomed (in or out) the scrolling animation bugs. Is your Chrome zoomed? Viewing the page without any zoom (100%) on Chrome will gain back easing.
I have the styles showing in the html, but this style “mCSB_scrollTools” is always displaying as display:none; And my regular scroll bar is always showing on the content container. Any idea why??
I found the issue. I was using max-height instead of height. Per your solution above, I used the code below to hook up my content to my scroll bar, and all is well now! Thanks!
(function($){
$(window).load(function(){
var maxHeightDiv=$(“#comment-items”),
maxHeight=parseInt(maxHeightDiv.css(“max-height”));
maxHeightDiv.mCustomScrollbar();
if(maxHeightDiv.find(“.mCSB_container”).outerHeight()>maxHeight){
maxHeightDiv.css({“height”:maxHeight}).mCustomScrollbar(“update”);
}else{
maxHeightDiv.css({“height”:”auto”}).mCustomScrollbar(“update”);
}
});
})(jQuery);
Hi
I’m trying to include this scrollbar in a website, and it’s almost working, just one thing is broken:
If I drag the scrollbar with my mouse, it remains “sticked” to my cursor, i.e. the
mouseUp
event seems to be somehow ignored. Clicking out of the area doesn’t help…Do you have any idea what could cause this, because i couldn’t figure it out.
Cheers
Cancel the last, I just saw what I needed in another post and copied it. Now the buttons appear. All I’d like to do now is change the length of the dragger bar and enable it to go right to the top and bottom of the dragger rail. I’m so close I can feel it. Any help would be much appreciated and if I can implement it on my site then it will be well worth a donation.
The scrollbar expands to full height by default and the dragger bar can be scrolled from top to bottom. All the styling is done via the CSS. I can’t really tell what you need so if you can send me a screen-shot or a link I might be able to help.
Hello, Thank you so much for responding to someone like me that has so little knowledge. I’d like just the dragger bar to be a little shorter and not take up so much room in the dragger rail. I tried setting the height to less and making a single CSS rule for the dragger bar but it didn’t work. I’d like to send a screenshot but I don’t know where to send it? This is a minor detail but I’d really like to get it to resemble my PSD composite as closely as possible. I would really appreciate any help. Many thanks.
Jack
By default, the dragger bar auto-adjusts its length according to scrollable content (the more the scrolling, the longer the dragger bar). If you see a long dragger bar, it means your content needs little scrolling (just like browser’s native scrollbar work).
If you want to have a non-adjustable fixed size dragger bar, set autoDraggerLength option parameter to false:
$(".content").mCustomScrollbar({ autoDraggerLength: false });
and set its (.mCSB_dragger) height normally via CSS.
Hello, your plugin and tutorial is exactly what I’m looking for to make my portfolio site work. However, I’m not a coder and I can’t see how to make the scroll buttons activate? I need the buttons to appear top and bottom. Could you tell me how to show them please.
Many thanks
Jack
With jquery > 1.8, I had problem making mCustomScrollbar work, then digging deeper, I changed all outerWidth() and outerHeight() to outerWidth(true) and outerHeight(true), since these methods have been updated. Now it works !!!
Hey paul i dont see any outerwidth or outerheight in the mcustomscrollbar script ?????
lol nevermind wasnt looking at the right script had another script named scrollbar that was still opened :p
Seems my scrollbar stops working in jQuery 1.8.x, fine in 1.7. Anyone encounter this? The DOM elements are correctly placed in the container but they are set to display:none and if I pull that style out of there with Firebug I can’t actually scroll with the bar that appears.
No JS errors though.
Any ideas?
Use jQuery 1.8.x with latest jQuery UI version (1.8.23+). I have a custom 1.8.23 build in the download archive.
Doh! It was just because my testing document had slipped in to quirks mode, and my $(window).height() was all messed up, making the scrollcontainer huge.
In a roundabout way though Paul you did help me realise that, so thanks for posting!
Hey.
I have a problem using this plugin and the jquery-ui autocomplete.
When I right click or left click on a autocomplete result, the content is automatically scrolling to top. Have you ever hear about this issue ? Do you know what can it be ?
I have made a stackoverflow to explain my problem :
Problem explained
I think I found the problem. You’re making some kind of check here on line 526 :
if (mCSB_containerY + focusedElemY >= 0 && mCSB_containerY + focusedElemY <= mCustomScrollBoxH - focusedElemH)
But
focusedElemY = focusedElem.position().top
and the position top returned is given relative to the first position ancestor, which is in the autocomplete the absolute positioned box.Thus wherever the focusedElemY will be on the content page, it will always return the same coordinates.
Dunno if i’m clear.
I think the solution would be to extend the position() method and give it the ancestor as argument.
I found this code :
/** * Get the current coordinates of the first element in the set of matched * elements, relative to the closest positioned ancestor element that * matches the selector. * @param {Object} selector */ jQuery.fn.positionAncestor = function(selector) { var left = 0; var top = 0; this.each(function(index, element) { // check if current element has an ancestor matching a selector // and that ancestor is positioned var $ancestor = $(this).closest(selector); if ($ancestor.length && $ancestor.css("position") !== "static") { var $child = $(this); var childMarginEdgeLeft = $child.offset().left - parseInt($child.css("marginLeft"), 10); var childMarginEdgeTop = $child.offset().top - parseInt($child.css("marginTop"), 10); var ancestorPaddingEdgeLeft = $ancestor.offset().left + parseInt($ancestor.css("borderLeftWidth"), 10); var ancestorPaddingEdgeTop = $ancestor.offset().top + parseInt($ancestor.css("borderTopWidth"), 10); left = childMarginEdgeLeft - ancestorPaddingEdgeLeft; top = childMarginEdgeTop - ancestorPaddingEdgeTop; // we have found the ancestor and computed the position // stop iterating return false; } }); return { left: left, top: top } };
Not tested yet but i think the idea is the same.
Thanks a lot for posting this, I’ll check it asap. Thanks for the feedback.
Thanks for a great article and plugin.
This is great, the only drawback is that it defaults to the OS scrollbar for touch devices, it should still be skinned (that’s the whole purpose of using this) and using touch events to scroll (there is the touchwipe jquery plugin to help with that).
Currently on iOS I also have to double click on the divs in order to be able to scroll and sometimes it doesn’t even work, is this a glitch caused by the plugin?
The plugin applies simple CSS overflow rules to iOS so I don’t think it’s the cause for such issues. I have an iPad 2 running iOS 6.0 and it works very smoothly so maybe it depends on the scrollable content or the device itself.
When I have enough time I’ll probably try implementing custom scrollbars for touch devices. I need time cause it’ll require additional coding and many hours for testing (consider Android, iOS, Windows phone, few OS versions for each one and at least half a dozen mobile browsers…)
Great work, Manos!
Is there any chance, that you’ll update the script to use horizontal and vertical scrollbars both on one div?
Or may be someone already modified it in such way?
No plans at the moment but you never know π
Is it possible to apply this scrollbar to the body?
I’m trying this, but not having any luck:
(function($){
$(window).load(function(){
$(“body”).mCustomScrollbar({
scrollEasing: false,
set_width:false,
set_height:false,
scrollButtons:{
enable:true
}
});
});
})(jQuery);
Not really. You can simulate a full-page custom scrollbar though, by adding a page wrapper div and call mCustomScrollbar on the content inside it.
See an example:
http://manos.malihu.gr/tuts/custom-scrollbar-plugin/full_page_demo/
but i think it can possible as u show it in the example page, U need to have below style to have it:
html, body{
height:100%;
}
hi,
i’ve got something like this: http://cssdeck.com/labs/collab/lxdo1dqq/0
i want to scroll in the generated content.
is there an option?
Thanks π
Somehow it doesn’t work for me on Windows 7 with Chrome 22.0.1229.94 anymore. It used to work out fine but stopped from one day to another. I uploaded a picture, but I guess it’s not much help.
I don’t get any error / warnings in the console. All scripts are loaded. $.fn.mCustomScrollbar is defined and I’m not experiencing js-related problems on any other page.
It works fine on me. Can you check it on another pc? Seems the plugin detects your chrome as a touch device. Did you attached any touch-screen monitors to your computer recently?
Edit: The link you provided is probably the wrong one π
π No idea how that could happen, but pretty funny though. Here’s the actual link: http://bit.ly/QPAMP7
My laptop is a tablet computer, so it has a touch sensitive screen. However, the scrollbars worked fine in the past. Is there any way I can force the plugin to display the scrollbars?
Ah, that’s the cause. It detects its touch-screen.
To force displaying the scrollbars, you need to edit jquery.mCustomScrollbar.js.
Find the line (39):
$(document).data("mCS-is-touch-device",true);
and change it to:
$(document).data("mCS-is-touch-device",false);
Doing this of course will make your scrollbars stop working on other touch devices.
Great plugin! Works flawlessly thanks very much!
Hello Malihu !
Your plugin is very great ! I love it.
But I have a bad news, it don’t work with the new jquery UI 1.9.
Be strong for that and have a good day.
I’ve tested it with jQuery UI 1.9.0 and it does work. Maybe your script isn’t loaded? Do you get any console errors?
Hi Manos,
I used this scrollbar in one of my projects which is still under development. While this works perfectly inside a div, I’ve been facing problems implementing it inside jQuery tabs.
My HTML:
<div class="allTabs"> <ul> <li><a href="#tabOne">ONE</a></li> <li><a href="#tabTwo">TWO</a></li> <li><a href="#tabThree">THREE</a></li> <li><a href="#tabFour">FOUR</a></li> </ul> <div id="tabOne"> <p>My Normal Text on First Tab</p> </div> <div id="tabTwo"> <p>My Normal Text on Second Tab</p> </div> <div id="tabThree"> <p>My Normal Text on Third Tab</p> </div> <div id="tabFour"> <p>My Lengthy Text on Left Half of Fourth Tab</p> <img class="myImage" src="my/image/url" width="320" height="400" /> <!-- This image on Right Half of Fourth Tab --> </div> </div>
JQuery Tabs script I am using: http://papermashup.com/simple-jquery-tabs/
Your JQuery script:
<script> (function($){ $(window).load(function(){ $(".allTabs").mCustomScrollbar(); }); })(jQuery); </script>
I have tried using “#tabFour” instead of “.allTabs” but my content just disappears and nothing happens.
I have also tried to implement some of the solutions, reading from comments and looking on both the pages. But unable to do this since I am a total newbie when it comes to jquery and javascripts.
I will want to use this scrollbar inside many sections that will have tabs.
Can you please help?
Hello,
The tabs plugin you’re using was not created to be used with other plugins, as it manipulates all divs inside it. You need to make some modifications in its js and css (e.g. changing .allTabs div to .allTabs>div) to make it work.
I’ve made a quick working demo that applies custom scrollbars on each tab content:
http://manos.malihu.gr/tuts/custom-scrollbar-plugin/tabs_temp_demo.html
View its source to see the modifications in the code.
Thank you very much, Manos.
After fiddling and trying various combinations, I was able to make the scrollbars appear inside all tabs by using > between all of the class and child elements in the css.
Now, I need to try it the way I want i.e. all tabs will have scrollable text on left half and an image on the right half.
A BIG THANK YOU AGAIN.
π
Hello,
I am experiencing a difficulty with the jQuery content scroller. If the content contains any links with ID or name attributes, the links will not work. How can I fix it? It’s really important for me…
Hi,
If you want to scroll to specific position within your content, please see Methods: scrollTo section of the post.
Hello, thanks for your reply. The problem isn’t so much with scrolling to a specific point of the page but in the links in it (only the ones linking into the same page; for example,
<a href="#link.html">link</a>
) which no longer work once I add the scrollbars; links to external pages work fine, but since I have several callbacks in the same pages, I need to figure out a way to make it work…Sorry for my bad English but I am italian! Hope it’s still understandable, though
I’ve put up an example here
http://misteridirapallo.altervista.org/scrollswlinks.html
As you can see, links within the div to which scrollbars are applied do not work, whereas the link to an external page works fine. Thing is, I plan to have several cross-links within the selfsame pages. Is there a way I can make this work?
Yes, that’s why I suggested checking Methods: scrollTo section. You need to do it via javascript.
In your page for example, to have LINK # 1 scroll to
<a name="par3">porta</a>
, you have to insert the following code below mCustomScrollbar function:$(".mistpage a[href='#par3']").click(function(e){ e.preventDefault(); $(".mistpage").mCustomScrollbar("scrollTo","a[name='par3']"); });
You can do the same for each of your links or you can create a single function that gets anchors href value and targets the anchors with same name attribute values.
Hope this helps
Tried it in local and it works, thanks you so much! π
Another thing – it’s possible to get the same results, but with links that are external to the page with the scrollbars (ie, a link outside the iframe, but that also scrolls to porta on click), and if so how?
Also, I have an unrelated question – I’m trying to use the scrolls in a page that uses another JS (a comment box from a third party website), though curiously it seems to work on an on-and-off basis in Firefox and Opera (while perfectly in Chrome, IE8 and Safari). The developer of the box asked me if it was possible to delay the scrollbars initialization of a few seconds until the other widget is loaded. Now correct me if I’m wrong but I seem to understand it’s what the Update method does, right?… So I should put the widget’s code within append? Just want to make sure I understood correctly what I’m doing π
You have your jQuery code inside the page which is loaded into the iframe, so it’s going to be tricky. You could probably use something like
$("#my-id", parent.document.body)
to target an anchor with id value “my-id” outside of the iframe:$("#my-id",parent.document.body).click(function(e){ e.preventDefault(); $(".mistpage").mCustomScrollbar("scrollTo","a[name='par3']"); });
Haven’t tested this, so I can’t really say it works.
The update method updates the scrollbar according to the new/updated content. So if another plugin manipulates content, you should call the update method after the changes are done.
You can try calling the mCustomScrollbar after other plugin calls, so it attaches the scrollbar last (after other plugins do their thing). Note that after the custom scrollbar is attached on an element, its actual content resides inside the .mCSB_container div, meaning that you can target its content (without messing with custom scrollbar markup) by
$(".mistpage .mCSB_container")
Tested the external links and works perfectly on simple text links, not on the menu but I guess it’s something to do with the dynamic menu I’m using (instead of calling back the item with the id, as the text link does, it loads the whole parent page within the iframe). But it’s no big deal since the contents are reacheable from within the pages themselves, so I’ll just remove the external links to the sections and leave the ones that take to the pages π
As for the page with two JS… I tried using update method, now it lets the other JS load fully, but then the scrolls themselves don’t o.O Did I make some mistake with the code? This is what I have so far;
(function($){ $(window).load(function(){ $(".mistpage").mCustomScrollbar({ scrollButtons:{ enable:true } }); }); $(".mistpage .mCSB_container").append("<span style="display:none;">***</span>"); $(".mistpage .mCSB_container").append("<script type="text/javascript" language="javascript" id="pnyxeDiscussItInitJs450467">try { var zpbw_webWidgetClientKey = "AyvGQA3IXXSCbbQ3Di49Jg"; var pnyxeDiscussIt = new PnyxeDiscussIt(); pnyxeDiscussIt.init("450467"); } catch (e) {}</script>"); $(".mistpage .mCSB_container").mCustomScrollbar("update"); })(jQuery);
Hi and first of all : pretty good job here.
Just wanted to ask a new functionnality. Your plugin works with touch devices, but unfortunately we can’t configure the way it works on them ( easing, no buttons appearing, etc…)
There is one jQuery that does the job but, it does not fit to my project because this one place the rail and cursor inside the page body ( which does not work in “fixed” situation).
https://github.com/inuyaksa/jquery.nicescroll
Do you think it might be possible?
best regards
Hello and thanks for the feedback.
At the moment there’s way too much fragmentation between mobile OS, versions and browsers to apply a single solution that would work well in each and all of them. For this reason, I decided to let mobile OS/browser to handle the scrolling of divs (since each one does its own thing).
I also didn’t want to stray away on how users scroll on touch devices by creating another non-native way of scrolling. For example, buttons scrolling is good for cursor but not so much for finger, simply because users are use to scroll by touch-and-swipe on their phones and tablets.
If at some point mobile browsers mature enough I might try implementing a non-native js scrolling with more options. Right now, there are mobile browsers that won’t even let you scroll divs other than the page itself (Opera, mobile IE etc.). Implementing overflow: auto on the div (the simplest of CSS properties) gave me headaches as it’s not supported by Android 2.x (the OS most phones use).
hello!
first of all, i want to say that is a great plugin π
then.. i want to tell my problem.. in that page http://lacullasulmare.com/?page_id=5 the scroll bar dose not scroll all the text content..
do you know why?
Hello,
When you dragger has a fixed size (like the rounded one in your page) you should set the autoDraggerLength option parameter to false (see Configuration section).
For example:
$(".content").mCustomScrollbar({ autoDraggerLength:false });