You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
13 KiB

5 years ago
  1. # Smooth Scroll [![Build Status](https://travis-ci.org/cferdinandi/smooth-scroll.svg)](https://travis-ci.org/cferdinandi/smooth-scroll)
  2. A lightweight script to animate scrolling to anchor links. Smooth Scroll works great with [Gumshoe](https://github.com/cferdinandi/gumshoe).
  3. **[View the Demo on CodePen →](https://codepen.io/cferdinandi/pen/wQzrdM)**
  4. [Getting Started](#getting-started) | [Scroll Speed](#scroll-speed) | [Easing Options](#easing-options) | [API](#api) | [What's new?](#whats-new) | [Known Issues](#known-issues) | [Browser Compatibility](#browser-compatibility) | [License](#license)
  5. *__Quick aside:__ you might not need this library. There's [a native CSS way to handle smooth scrolling](https://gomakethings.com/smooth-scrolling-links-with-only-css/) that might fit your needs.*
  6. <hr>
  7. ### Want to learn how to write your own vanilla JS plugins? Check out my [Vanilla JS Pocket Guides](https://vanillajsguides.com/) or join the [Vanilla JS Academy](https://vanillajsacademy.com) and level-up as a web developer. 🚀
  8. <hr>
  9. ## Getting Started
  10. Compiled and production-ready code can be found in the `dist` directory. The `src` directory contains development code.
  11. ### 1. Include Smooth Scroll on your site.
  12. There are two versions of Smooth Scroll: the standalone version, and one that comes preloaded with polyfills for `closest()`, `requestAnimationFrame()`, and `CustomEvent()`, which are only supported in newer browsers.
  13. If you're including your own polyfills or don't want to enable this feature for older browsers, use the standalone version. Otherwise, use the version with polyfills.
  14. **Direct Download**
  15. You can [download the files directly from GitHub](https://github.com/cferdinandi/smooth-scroll/archive/master.zip).
  16. ```html
  17. <script src="path/to/smooth-scroll.polyfills.min.js"></script>
  18. ```
  19. **CDN**
  20. You can also use the [jsDelivr CDN](https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll/dist/). I recommend linking to a specific version number or version range to prevent major updates from breaking your site. Smooth Scroll uses semantic versioning.
  21. ```html
  22. <!-- Always get the latest version -->
  23. <!-- Not recommended for production sites! -->
  24. <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll/dist/smooth-scroll.polyfills.min.js"></script>
  25. <!-- Get minor updates and patch fixes within a major version -->
  26. <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll@15/dist/smooth-scroll.polyfills.min.js"></script>
  27. <!-- Get patch fixes within a minor version -->
  28. <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll@15.0/dist/smooth-scroll.polyfills.min.js"></script>
  29. <!-- Get a specific version -->
  30. <script src="https://cdn.jsdelivr.net/gh/cferdinandi/smooth-scroll@15.0.0/dist/smooth-scroll.polyfills.min.js"></script>
  31. ```
  32. **NPM**
  33. You can also use NPM (or your favorite package manager).
  34. ```bash
  35. npm install smooth-scroll
  36. ```
  37. ### 2. Add the markup to your HTML.
  38. No special markup needed&mdash;just standard anchor links. Give the anchor location an ID just like you normally would.
  39. ```html
  40. <a data-scroll href="#bazinga">Anchor Link</a>
  41. ...
  42. <div id="bazinga">Bazinga!</div>
  43. ```
  44. ***Note:*** *Smooth Scroll does not work with `<a name="anchor"></a>` style anchors. It requires IDs.*
  45. ### 3. Initialize Smooth Scroll.
  46. In the footer of your page, after the content, initialize Smooth Scroll by passing in a selector for the anchor links that should be animated. And that's it, you're done. Nice work!
  47. ```html
  48. <script>
  49. var scroll = new SmoothScroll('a[href*="#"]');
  50. </script>
  51. ```
  52. ***Note:*** *The `a[href*="#"]` selector will apply Smooth Scroll to all anchor links. You can selectively target links using any other selector(s) you'd like. Smooth Scroll accepts multiple selectors as a comma separated list. Example: `'.js-scroll, [data-scroll], #some-link'`.*
  53. ## Scroll Speed
  54. Smooth Scroll allows you to adjust the speed of your animations with the `speed` option.
  55. This a number representing the amount of time in milliseconds that it should take to scroll 1000px. Scroll distances shorter than that will take less time, and scroll distances longer than that will take more time. The default is 300ms.
  56. ```js
  57. var scroll = new SmoothScroll('a[href*="#"]', {
  58. speed: 300
  59. });
  60. ```
  61. If you want all of your animations to take exactly the same amount of time (the value you set for `speed`), set the `speedAsDuration` option to `true`.
  62. ```js
  63. // All animations will take exactly 500ms
  64. var scroll = new SmoothScroll('a[href*="#"]', {
  65. speed: 500,
  66. speedAsDuration: true
  67. });
  68. ```
  69. ## Easing Options
  70. Smooth Scroll comes with about a dozen common easing patterns. [Here's a demo of the different patterns.](https://codepen.io/cferdinandi/pen/jQMGaB)
  71. **Linear**
  72. *Moves at the same speed from start to finish.*
  73. - `Linear`
  74. **Ease-In**
  75. *Gradually increases in speed.*
  76. - `easeInQuad`
  77. - `easeInCubic`
  78. - `easeInQuart`
  79. - `easeInQuint`
  80. **Ease-In-Out**
  81. *Gradually increases in speed, peaks, and then gradually slows down.*
  82. - `easeInOutQuad`
  83. - `easeInOutCubic`
  84. - `easeInOutQuart`
  85. - `easeInOutQuint`
  86. **Ease-Out**
  87. *Gradually decreases in speed.*
  88. - `easeOutQuad`
  89. - `easeOutCubic`
  90. - `easeOutQuart`
  91. - `easeOutQuint`
  92. You can also pass in your own custom easing pattern [using the `customEasing` option](#global-settings).
  93. ```js
  94. var scroll = new SmoothScroll('a[href*="#"]', {
  95. // Function. Custom easing pattern
  96. // If this is set to anything other than null, will override the easing option above
  97. customEasing: function (time) {
  98. // return <your formulate with time as a multiplier>
  99. // Example: easeInOut Quad
  100. return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time;
  101. }
  102. });
  103. ```
  104. ## API
  105. Smooth Scroll includes smart defaults and works right out of the box. But if you want to customize things, it also has a robust API that provides multiple ways for you to adjust the default options and settings.
  106. ### Options and Settings
  107. You can pass options and callbacks into Smooth Scroll when instantiating.
  108. ```javascript
  109. var scroll = new SmoothScroll('a[href*="#"]', {
  110. // Selectors
  111. ignore: '[data-scroll-ignore]', // Selector for links to ignore (must be a valid CSS selector)
  112. header: null, // Selector for fixed headers (must be a valid CSS selector)
  113. topOnEmptyHash: true, // Scroll to the top of the page for links with href="#"
  114. // Speed & Duration
  115. speed: 500, // Integer. Amount of time in milliseconds it should take to scroll 1000px
  116. speedAsDuration: false, // If true, use speed as the total duration of the scroll animation
  117. durationMax: null, // Integer. The maximum amount of time the scroll animation should take
  118. durationMin: null, // Integer. The minimum amount of time the scroll animation should take
  119. clip: true, // If true, adjust scroll distance to prevent abrupt stops near the bottom of the page
  120. offset: function (anchor, toggle) {
  121. // Integer or Function returning an integer. How far to offset the scrolling anchor location in pixels
  122. // This example is a function, but you could do something as simple as `offset: 25`
  123. // An example returning different values based on whether the clicked link was in the header nav or not
  124. if (toggle.classList.closest('.my-header-nav')) {
  125. return 25;
  126. } else {
  127. return 50;
  128. }
  129. },
  130. // Easing
  131. easing: 'easeInOutCubic', // Easing pattern to use
  132. customEasing: function (time) {
  133. // Function. Custom easing pattern
  134. // If this is set to anything other than null, will override the easing option above
  135. // return <your formulate with time as a multiplier>
  136. // Example: easeInOut Quad
  137. return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time;
  138. },
  139. // History
  140. updateURL: true, // Update the URL on scroll
  141. popstate: true, // Animate scrolling with the forward/backward browser buttons (requires updateURL to be true)
  142. // Custom Events
  143. emitEvents: true // Emit custom events
  144. });
  145. ```
  146. ### Custom Events
  147. Smooth Scroll emits three custom events:
  148. - `scrollStart` is emitted when the scrolling animation starts.
  149. - `scrollStop` is emitted when the scrolling animation stops.
  150. - `scrollCancel` is emitted if the scrolling animation is canceled.
  151. All three events are emitted on the `document` element and bubble up. You can listen for them with the `addEventListener()` method. The `event.detail` object includes the `anchor` and `toggle` elements for the animation.
  152. ```js
  153. // Log scroll events
  154. var logScrollEvent = function (event) {
  155. // The event type
  156. console.log('type:', event.type);
  157. // The anchor element being scrolled to
  158. console.log('anchor:', event.detail.anchor);
  159. // The anchor link that triggered the scroll
  160. console.log('toggle:', event.detail.toggle);
  161. };
  162. // Listen for scroll events
  163. document.addEventListener('scrollStart', logScrollEvent, false);
  164. document.addEventListener('scrollStop', logScrollEvent, false);
  165. document.addEventListener('scrollCancel', logScrollEvent, false);
  166. ```
  167. ### Methods
  168. Smooth Scroll also exposes several public methods.
  169. #### animateScroll()
  170. Animate scrolling to an anchor.
  171. ```javascript
  172. var scroll = new SmoothScroll();
  173. scroll.animateScroll(
  174. anchor, // Node to scroll to. ex. document.querySelector('#bazinga')
  175. toggle, // Node that toggles the animation, OR an integer. ex. document.querySelector('#toggle')
  176. options // Classes and callbacks. Same options as those passed into the init() function.
  177. );
  178. ```
  179. **Example 1**
  180. ```javascript
  181. var scroll = new SmoothScroll();
  182. var anchor = document.querySelector('#bazinga');
  183. scroll.animateScroll(anchor);
  184. ```
  185. **Example 2**
  186. ```javascript
  187. var scroll = new SmoothScroll();
  188. var anchor = document.querySelector('#bazinga');
  189. var toggle = document.querySelector('#toggle');
  190. var options = { speed: 1000, easing: 'easeOutCubic' };
  191. scroll.animateScroll(anchor, toggle, options);
  192. ```
  193. **Example 3**
  194. ```javascript
  195. // You can optionally pass in a y-position to scroll to as an integer
  196. var scroll = new SmoothScroll();
  197. scroll.animateScroll(750);
  198. ```
  199. #### cancelScroll()
  200. Cancel a scroll-in-progress.
  201. ```javascript
  202. var scroll = new SmoothScroll();
  203. scroll.cancelScroll();
  204. ```
  205. ***Note:*** *This does not handle focus management. The user will stop in place, and focus will remain on the anchor link that triggered the scroll.*
  206. #### destroy()
  207. Destroy the current initialization. This is called automatically in the `init` method to remove any existing initializations.
  208. ```javascript
  209. var scroll = new SmoothScroll();
  210. scroll.destroy();
  211. ```
  212. ### Fixed Headers
  213. If you're using a fixed header, Smooth Scroll will automatically offset scroll distances by the header height. Pass in a valid CSS selector for your fixed header as an option to the `init`.
  214. If you have multiple fixed headers, pass in the last one in the markup.
  215. ```html
  216. <nav data-scroll-header>
  217. ...
  218. </nav>
  219. ...
  220. <script>
  221. var scroll = new SmoothScroll('.some-selector',{
  222. header: '[data-scroll-header]'
  223. });
  224. </script>
  225. ```
  226. ## What's new?
  227. Scroll duration now varies based on distance traveled. If you want to maintain the old scroll animation duration behavior, set the `speedAsDuration` option to `true`.
  228. ## Known Issues
  229. ### Reduce Motion Settings
  230. This isn't really an "issue" so-much as a question I get a lot.
  231. Smooth Scroll respects [the `Reduce Motion` setting](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) available in certain operating systems. In browsers that surface that setting, Smooth Scroll will not run and will revert to the default "jump to location" anchor link behavior.
  232. I've decided to respect user preferences of developer desires here. This is *not* a configurable setting.
  233. ### `<body>` styling
  234. If the `<body>` element has been assigned a height of `100%` or `overflow: hidden`, Smooth Scroll is unable to properly calculate page distances and will not scroll to the right location. The `<body>` element can have a fixed, non-percentage based height (ex. `500px`), or a height of `auto`, and an `overflow` of `visible`.
  235. ### Animating from the bottom
  236. Animated scrolling links at the very bottom of the page (example: a "scroll to top" link) will stop animated almost immediately after they start when using certain easing patterns. This is an issue that's been around for a while and I've yet to find a good fix for it. I've found that `easeOut*` easing patterns work as expected, but other patterns can cause issues. [See this discussion for more details.](https://github.com/cferdinandi/smooth-scroll/issues/49)
  237. ### Scrolling to an anchor link on another page
  238. This, unfortunately, cannot be done well.
  239. Most browsers instantly jump you to the anchor location when you load a page. You could use `scrollTo(0, 0)` to pull users back up to the top, and then manually use the `animateScroll()` method, but in my experience, it results in a visible jump on the page that's a worse experience than the default browser behavior.
  240. ## Browser Compatibility
  241. Smooth Scroll works in all modern browsers, and IE 9 and above.
  242. Smooth Scroll is built with modern JavaScript APIs, and uses progressive enhancement. If the JavaScript file fails to load, or if your site is viewed on older and less capable browsers, anchor links will jump the way they normally would.
  243. *__Note:__ Smooth Scroll will not run&mdash;even in supported browsers&mdash;if users have `Reduce Motion` enabled. [Learn more in the "Known Issues" section.](#reduce-motion-settings)*
  244. ### Polyfills
  245. Support back to IE9 requires polyfills for `closest()`, `requestAnimationFrame()`, and `CustomEvent()`. Without them, support starts with Edge.
  246. Use the included polyfills version of Smooth Scroll, or include your own.
  247. ## License
  248. The code is available under the [MIT License](LICENSE.md).