1 | # [scrollnav.js][1]
|
2 |
|
3 | [![npm](https://img.shields.io/npm/v/scrollnav.svg)](https://www.npmjs.com/package/scrollnav)
|
4 | [![Build Status](https://travis-ci.org/jimmynotjim/scrollnav.svg?branch=master)](https://travis-ci.org/jimmynotjim/scrollnav)
|
5 | [![Codecov](https://img.shields.io/codecov/c/github/codecov/example-python.svg)](https://codecov.io/gh/jimmynotjim/scrollnav)
|
6 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/jimmynotjim/scrollnav/blob/master/LICENSE-MIT)
|
7 |
|
8 | ## Introduction
|
9 |
|
10 | scrollnav.js is a small (2.4kb gzipped), dependency free JavaScript plugin
|
11 | for auto generating single page navigation with active highlighting. Useful
|
12 | for creating a Table of Contents for a large document (think Wikis),
|
13 | navigation for a single page website, or anything else you might think of.
|
14 |
|
15 | scrollnav works by scanning a block of content for section landmarks
|
16 | (typically heading elements) and generating a list of links from those
|
17 | landmarks. It then tracks the scroll location of the document and highlights
|
18 | the appropriate link. While previous versions injected wrappers within the
|
19 | content, the current version (ver 3) takes a much lighter approach, only
|
20 | changing the DOM as necessary. Visit the live demo at [scrollnav.com][1]
|
21 | to see for yourself.
|
22 |
|
23 | ## Browser Compatibility
|
24 |
|
25 | scrollnav supports all browsers that are ES5-compliant (IE8 and below are
|
26 | not supported).
|
27 |
|
28 | ## Getting Started
|
29 |
|
30 | The compiled, production ready plugin is available in the `dist` directory.
|
31 | Please don't use the `src` directory unless you plan to build the entire
|
32 | source.
|
33 |
|
34 | ### Install
|
35 |
|
36 | #### Download
|
37 |
|
38 | [scrollnav@v3.0.1](https://unpkg.com/scrollnav@3.0.1/dist/scrollnav.min.umd.js)
|
39 |
|
40 | ```html
|
41 | <script src="[your assets directory]/scrollnav.min.umd.js"></script>
|
42 | ```
|
43 |
|
44 | #### CDN
|
45 |
|
46 | ```html
|
47 | <script src="https://unpkg.com/scrollnav@3.0.1/dist/scrollnav.min.umd.js"></script>
|
48 | ```
|
49 |
|
50 | #### Package manager
|
51 |
|
52 | [Yarn][13]: `yarn add scrollnav`
|
53 |
|
54 | It's the new hotness, it's also better at managing dependencies than all it's predecesors.
|
55 |
|
56 | [NPM][12]: `npm install scrollnav`
|
57 |
|
58 | Good'ol NPM, it's always there, except when it isn't. Things have settled down a bit, but it was dicey there for a while. Even still, there's a reason even Yarn uses the NPM registry.
|
59 |
|
60 | [Bower][11]: `bower install scrollnav --save`
|
61 |
|
62 | The folks from Bower no longer recommend using Bower. Luckily they've provided a guide on [how to migrate to Yarn](https://bower.io/blog/2017/how-to-migrate-away-from-bower/). If you don't want to or can't migrate, scrollnav will continue to be available on Bower as long as it continues to run.
|
63 |
|
64 |
|
65 | ### Usage
|
66 |
|
67 | scrollnav works by scanning the given [HTML Node Element][25] for section
|
68 | landmarks, by default `h2` elements, that it then uses to generate the nav.
|
69 | If we were to look at a typical document, it might look like this:
|
70 |
|
71 | ```html
|
72 | <div class="main-content">
|
73 | <h2>First section</h2>
|
74 | ...
|
75 | <h2>Second section</h2>
|
76 | ...
|
77 | <h2>Third section</h2>
|
78 | ...
|
79 | </div>
|
80 | ```
|
81 |
|
82 | #### Initialize
|
83 |
|
84 | First, initialize scrollnav with the HTML Element. In this example we'll use
|
85 | `.querySelector()` but you could also use `.getElementByID()` or
|
86 | `.getElementByClassName()`.
|
87 |
|
88 | ```js
|
89 | const content = document.querySelector('.main-content');
|
90 | scrollnav.init(content);
|
91 | ```
|
92 |
|
93 | scrollnav will then loop through the the `h2` elements, add an ID if they don't
|
94 | already have one, build the nav, and then inject it just before the content
|
95 | Node. The result for our example document would look like this:
|
96 |
|
97 | ```html
|
98 | <nav class="scroll-nav">
|
99 | <ol class="scroll-nav__list">
|
100 | <li class="scroll-nav__item">
|
101 | <a class="scroll-nav__link" href="#scroll-nav__1">
|
102 | First heading
|
103 | <a>
|
104 | </li>
|
105 | ...
|
106 | </ol>
|
107 | </nav>
|
108 | <div class="main-content">
|
109 | <h2 id="scroll-nav__1">First Heading</h2>
|
110 | ...
|
111 | </div>
|
112 | ```
|
113 |
|
114 | #### Styles
|
115 |
|
116 | To keep the plugin simple there are no styles added to the navigation, that's
|
117 | all up to you ([view the demo site][1] for exmaples of the most common use
|
118 | cases). The nav structure provides [BEM Methodology][23] class names for each
|
119 | of the elements to provide consistent styling hooks (for a good overview read
|
120 | [MindBEMding - getting your head 'round BEM syntax][24]). As the user scrolls
|
121 | the document, scrollnav adds a `scroll-nav__item--active` modifier for the
|
122 | item's relative section that currently intersects with the activation
|
123 | threshold ([enable `debug` mode](#additional-options) to highlight the
|
124 | threshold).
|
125 |
|
126 | ### Settings and options
|
127 |
|
128 | scrollnav includes some default settings that work for most situations, but if
|
129 | your project requires a bit more customization, scrollnav can most likely meet
|
130 | those. To modify either, pass in a single object (include settings and options
|
131 | as one object) as the second argument like this:
|
132 |
|
133 | ```js
|
134 | scrollnav.init(content, {
|
135 | key: value
|
136 | });
|
137 | ```
|
138 |
|
139 | #### Default settings
|
140 |
|
141 | The following settings are editable to overwrite the default.
|
142 |
|
143 | ```js
|
144 | {
|
145 | sections: 'selector',
|
146 | // string
|
147 | //
|
148 | // Sets the querySelector for the content's section landmarks, by default
|
149 | // it's 'h2'.
|
150 |
|
151 | insertTarget: targetNode,
|
152 | // HTML Node
|
153 | //
|
154 | // Sets the target Node for injecting the navigation, by default it's the
|
155 | // content Node passed to scrollnav.
|
156 |
|
157 | insertLocation: 'relativeLocation'
|
158 | // string
|
159 | //
|
160 | // Sets the injection location relative to the insertTarget, by default it's
|
161 | // 'before'.
|
162 | //
|
163 | // available options are 'append', 'prepend', 'after', or 'before'
|
164 |
|
165 | easingStyle: 'easingName',
|
166 | // string
|
167 | //
|
168 | // Sets the easing type for the scroll animation that is triggered by the
|
169 | // click event on a nav item, by default it's 'easeOutQuad'.
|
170 | //
|
171 | // available options are 'linear' 'easeInQuad', 'easeOutQuad',
|
172 | // 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic',
|
173 | // 'easeInQuart', 'easeOutQuart', 'easeInOutQuart', 'easeInQuint',
|
174 | // 'easeOutQuint', easeInOutQuint
|
175 |
|
176 | updateHistory: true
|
177 | // boolean
|
178 | //
|
179 | // Sets the history behavior when a nav item is clicked, by default it's true
|
180 | }
|
181 | ```
|
182 |
|
183 | #### Additional options
|
184 |
|
185 | These additional options are editable but are not set by default.
|
186 |
|
187 | ```js
|
188 | {
|
189 | subSections: '...',
|
190 | // string
|
191 | //
|
192 | // Sets the querySelector for the content's sub-section landmarks.
|
193 |
|
194 | onScroll: function() {...},
|
195 | // function
|
196 | //
|
197 | // Sets the callback to be triggered after the window scrolls when triggered
|
198 | // by the click event on a nav item.
|
199 |
|
200 | onInit: function() {...},
|
201 | // function
|
202 | //
|
203 | // Sets the callback to be triggered after the .init() method has completed.
|
204 |
|
205 | onUpdatePositions: function() {...},
|
206 | // function
|
207 | //
|
208 | // Sets the callback to be triggered after the .updatePositions() method
|
209 | // has completed.
|
210 |
|
211 | onDestroy: function() {...},
|
212 | // function
|
213 | //
|
214 | // Sets the callback to be triggered after the .destroy() method has
|
215 | // completed.
|
216 |
|
217 | debug: false
|
218 | // boolean
|
219 | //
|
220 | // Enables scrollnav's built in debug mode to log errors to the console and
|
221 | // display the active area threshold on screen, helpful for when you've hit a
|
222 | // snag you can't easily identify.
|
223 | }
|
224 | ```
|
225 |
|
226 | #### Available methods
|
227 |
|
228 | In addition to the `.init()` method scrollnav provides two additional public
|
229 | methods.
|
230 |
|
231 | #### destroy()
|
232 |
|
233 | To remove the current instance of scrollnav call the destroy method. If you
|
234 | need to trigger a callback after scrollnav has been removed, use the
|
235 | `onDestroy` option described above (passed either in the original init or with
|
236 | the destroy method).
|
237 |
|
238 | ```js
|
239 | scrollnav.destroy();
|
240 | ```
|
241 |
|
242 | #### updatePositions()
|
243 |
|
244 | scrollnav doesn't track outside DOM changes. If your page's content is dynamic
|
245 | and updates after scrollnav is initialized you'll need to recalcuate the
|
246 | position data with the updatePositions method. If you need to trigger a
|
247 | callback after the position data has been recalculated, use the
|
248 | `onUpdatePositions` option described above (passed either in the original init
|
249 | or with the updatePositions method).
|
250 |
|
251 | ```js
|
252 | scrollnav.updatePositions();
|
253 | ```
|
254 |
|
255 | ## Issues
|
256 |
|
257 | Please read and understand the [Contributing Guidelines][4] prior to [opening
|
258 | an issue][2]. Ensuring your issue conforms to the guidelines gives it a better
|
259 | chance I'll be able to help address it.
|
260 |
|
261 | ## Questions
|
262 | For questions about using scrollnav in your own project, your best bet is to
|
263 | post it to [Stack Overflow][21]. The community there is great at lending a hand
|
264 | and can often respond faster than I can, plus it becomes searchable for future
|
265 | developers who may run into the same question. If you're still stuck, please
|
266 | feel free to reach out to me to ask for help or clarification, I'm [@jimmynotim
|
267 | on Twitter][22].
|
268 |
|
269 | ## Changelog
|
270 |
|
271 | v3.0.1 is the current stable release. For detailed changes in each release
|
272 | please refer to the [release notes][5]. Please be sure you understand the
|
273 | changes before updating, v3 is a complete re-write of the plugin (as is v2
|
274 | compared to v1 before it).
|
275 |
|
276 | ## Contributions
|
277 |
|
278 | scrollnav is built and maintained by [James Wilson (@jimmynotjim)][31].
|
279 | I wouldn't be able to continue this project without a lot of help from the
|
280 | Open Source community. I welcome feedback and enhancements, but first, please
|
281 | make sure to read the [Contributing Guide][4].
|
282 |
|
283 | Thank you to everyone who has already contributed to scrollnav!
|
284 |
|
285 | * [Chris Garcia (@pixelbandito)][43]
|
286 | * [Eric Clemmons (@ericclemmons)][32]
|
287 | * [Felix Borzik (@Borzik)][39]
|
288 | * [Jeff Byrnes (@jeffbyrnes)][33]
|
289 | * [Jeff Coburn (@coburnicus)][34]
|
290 | * [Jen Germann (@germanny)][35]
|
291 | * [Jim Schmid (@sheeep)][44]
|
292 | * [Marc Amos (@marcamos)][38]
|
293 | * [Masud Rahman (@frutiger)][40]
|
294 | * [Meghdad Hadidi (@MeghdadHadidi)][37]
|
295 | * [Michael Benin (@michael-benin-CN)][45]
|
296 | * [Rob Loach (@RobLoach)][41]
|
297 | * [Thomas Guillary @thomasguillory][46]
|
298 | * [Will Moore (@willthemoor)][42]
|
299 | * [Wizcover (@wizcover)][36]
|
300 |
|
301 | ## License
|
302 |
|
303 | scrollnav is Copyright © 2012-2018 James Wilson, released under the
|
304 | [MIT license][3]. This means you can re-create, edit or share the plugin as
|
305 | long as you maintain the same open licensing.
|
306 |
|
307 |
|
308 | [1]: http://scrollnav.com
|
309 | [2]: https://github.com/jimmynotjim/scrollnav/issues
|
310 | [3]: https://github.com/jimmynotjim/scrollnav/blob/master/LICENSE-MIT
|
311 | [4]: https://github.com/jimmynotjim/scrollnav/blob/master/CONTRIBUTING.md
|
312 | [5]: https://github.com/jimmynotjim/scrollnav/blob/master/CHANGELOG.md
|
313 |
|
314 | [11]: https://bower.io/
|
315 | [12]: https://www.npmjs.com/package/scrollnav
|
316 | [13]: https://yarnpkg.com/en/package/scrollnav
|
317 |
|
318 | [21]: https://stackoverflow.com/questions
|
319 | [22]: https://twitter.com/jimmynotjim
|
320 | [23]: http://bem.info/method/
|
321 | [24]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
|
322 | [25]: https://developer.mozilla.org/en-US/docs/Web/API/Element
|
323 |
|
324 | [31]: http://github.com/jimmynotjim
|
325 | [32]: https://github.com/ericclemmons
|
326 | [33]: https://github.com/jeffbyrnes
|
327 | [34]: https://github.com/coburnicus
|
328 | [35]: https://github.com/germanny
|
329 | [36]: https://github.com/wizcover
|
330 | [37]: https://github.com/MeghdadHadidi
|
331 | [38]: http://github.com/marcamos
|
332 | [39]: http://github.com/borzik
|
333 | [40]: http://github.com/frutiger
|
334 | [41]: http://github.com/RobLoach
|
335 | [42]: http://github.com/willthemoor
|
336 | [43]: http://github.com/pixelbandito
|
337 | [44]: http://github.com/sheeep
|
338 | [45]: http://github.com/michael-benin-CN
|
339 | [46]: http://github.com/thomasguillory
|
340 |
|