The problem of styling the browser scrollbar is still relevant, despite the huge number of scripts designed to solve this problem. Consider the implementation of a stylized scrollbar, as close as possible to the native behavior of the browser.
There are two main approaches for styling a scrollbar with HTML / CSS, each of which has its own pros and cons:
- Scroll emulation with JavaScript
- Javascript wrapper over native scrolling
Scroll emulation with JavaScript
The great advantage of this approach is that it is a fully JavaScript solution. Thanks to this, this solution is easier to develop and is as cross-browser as possible (meaning that the scroll behavior in all browsers will be the same, regardless of the implementation of the browser scroll), having a minimal impact on the HTML structure and the applied CSS styles. JScrollPane, FleXcroll, Tiny Scrollbar and many others use this approach.
')
However, the strength of this approach is at the same time its weakness:
- Difficulty or impossibility to emulate / intercept all events
- JavaScript emulation is slower than native scrolling
Javascript wrapper over native scrolling
This approach is that the native scroll is hidden by means of HTML / CSS, while continuing to fulfill its purpose - scrolling content. Such a solution is preferable for the reason that the native scroll works better than the emulated one anyway. Many have tried to create plug-ins based on this approach, but due to the lack of any standards, the cross-browser implementation is very complicated, and imposes certain restrictions on the HTML structure and the used CSS styles. For this reason, many developers create an implementation of only a vertical scroll that behaves more or less predictably in all browsers.
One of the quite good implementations of such an approach was described quite recently in the article
Crossbrowser customization of the system scrollbar with a rather detailed explanation.
The invention of the tricycle
One of the reasons for creating the
next bike was that the script search for styling a scroll showed more than 20 different plug-ins, none of which was suitable for the ordered project. Most of the known plug-ins did not work due to slow work with a large number of initialized scrolls on the page. Others did not fit due to inconvenient implementation or insufficient cross-browser compatibility.
It was decided to make its own implementation that meets the following requirements:
- The behavior of the scroll should be as close as possible to the native
- Vertical and horizontal scrollbar
- Minimum processor load
- Full styling with HTML / CSS
- The ability to apply your HTML structure for a scrollbar, or specify a plugin to use an already existing element as a scrollbar
- Automatic scrolling when the contents are changed or the container size is changed without the need to re-initialize the script
- The width and height of the container can be set either in pixels or as a percentage, or limited by CSS max-height / max-width
- The scroll can be located anywhere in the container or outside it.
- Automatic scrollbar size calculation, or value set via CSS styles
- Support IE7 +, Firefox, Chrome, Opera, Safari
- The ability to "out of the box" disable scrolling for mobile browsers
As an approach, the decision was made to make a plugin in the form of JavaScript wrappers over a native scroll - i.e. leave the functionality of the native scroll, hide the native scroll with CSS and show a stylized scroll. This gives the advantage that you do not need to emulate the behavior of the standard scroll, but only catch changes in positioning using JavaScript.
It was still impossible to avoid full scrolling emulation - it is necessary to emulate the scrolling behavior when the mouse is over the styled scroll: catch the mouse scroll, drag & drop, clicks on the scroll itself and arrows. The ideal solution “I connected and forgot”, of course, did not work. But almost all of the goals were achieved in full.
On a note
It should be remembered that for a stylized scrollbar to work, a certain HTML structure is needed, for which the source javascript container is wrapped in a different container when initialized. For this reason, there are some features of use, HTML structures and CSS styles:
- Source container should not contain inline styles.
- You should avoid using padding / margin for the container. If you need an indentation, it is better to add another container with the necessary indentation.
- When changing the contents of the container, you should not refer to the container by class, since these classes will be used by the wrapper container
The minor drawbacks include the difference in the height / width of the scroll wheel with the mouse wheel in cases where the mouse is over the contents of the container (native behavior) and when the mouse is over the scrollbar (emulated scroll). There are several ideas that are quite difficult to implement, so leave them "for later."
Also, until you can not get rid of the unpleasant effect of scrolling the container when you select text in WebKit browsers Chrome and Safari. Partially managed to do this when using outer-scroll (there is a demonstration).
Notes
Due to the difference in scrolling behavior not only in different browsers, but also in different versions of the same browser (yes, the browser itself), I had to try a lot of margin / padding / border / position combinations to calculate similar behavior. During the search for a solution, several interesting features were found:
- In IE8 - bugs using max-height: in some cases, the renderer of version 8 of IE crashes, or tries to make the height of the container equal to max-height (official bug release version)
- WebKit-browsers (Chrome, Safari) when scrolling text make the internal container scroll, “exposing” the hidden scrollbar
- If the content exceeds the size of the container, then the display of the right and bottom padding is left to the discretion of the browser itself.
- When searching for plugins, to quickly find out whether the standard scrolling mechanism is used, just click on the mouse scrolling over the scrollable content
Update to version 0.1.3 (20130425):
- scrolling emulation is improved: now the mouse wheel scrolling over the emulated scroll works almost identical to the natural scroll; also changed the behavior when you press and hold the mouse on the substrate scrollbar
- fixed CSS positioning, in which there was an "extra" container shift when text was selected in WebKit browsers Google Chrome / Safari
Update to version 0.1.4 (20130430):
- horizontal scrolling with the mouse over the horizontal scrollbar
- added a disableBodyScroll option to disable page scrolling when the container scrolls. In this option, I had to disable the native behavior of the browser and emulate the scroll through JavaScript
Update to version 0.1.6 (20131018):
- Added option to ignore scrolling initialization on mobile devices
- drag support added for scrolling on touch devices
Update to version 0.1.7 (20140307):
- added a hack to correct the appearance of a scrollbar with a 1-pixel gap in the IE
Update to version 0.1.8 (20140308):
- fixed bug with displaying horizontal scrollbar if the height of the contents is less than the height of the container (cases with height: 100%)
Update to version 0.1.9 (20140310):
- fixed bug with displaying vertical scrollbar if the content contains a div with height: 100%; overflow: hidden; inside of which is a div with a height greater than the height of the outer container (thanks for the feedback and comments from Evangeline Rei )
- added autoUpdate option responsible for automatic re-initialization of the scrollbar when resizing the content / container
Update to version 0.2.0 (20140312):
- Added onUpdate option for manually recalculating the size of the scrollbar. Thanks to this option, a scrollbar was added as a page map.
- Added stepScrolling option responsible for step-by-step scrolling to the place where the mouse button is held down on the scrollbar. if the option is disabled, the contents will be scrolled immediately to the location of the mouse, otherwise step-by-step scrolling will be performed with acceleration to the mouse-holding position (scrolling behavior emulation)
- hide / show scrollbars completely transferred to CSS
- changed the behavior of onInit - now the function starts only once during initialization
Update to version 0.2.1 (20140323):
- fixed bug with scrolling to # anchor-element when horizontal scroll becomes visible
Update to version 0.2.2 (20140411):
- Fixed a bug with the initialization of several scrollbars with default settings
- Added scroll-element_corner element for easy CSS corner settings if both scrollbars are visible.
Update to version 0.2.3 (20140703):
- fixed bug with visible scrollbar when zoom is changed in browser
- Fixed a bug with incorrect initialization of the size of the scrollbar for IE using CSS * {box-sizing: border-box; }
- added callback function onScroll, which makes it easier to determine the degree of scrolling of the container
- scrollbar can be used as a directive for an excellent Angular.JS framework
- added the ability to override default values ​​via jQueryScrollbarOptions global variable before loading the plugin
- optimized container resize check
Update to version 0.2.4 (20140715):
- added the ability to stylize a scrollbar for TEXTAREA
finally