Lightweight package for highlighting menu items as you scroll the page, also scrolling to target section when item clicked. Use as a vue component/directive or in vanilla js.

Overview

navscroll-js

npm npm license

Installation

This package is available on npm.

Using npm:

npm install --save navscroll

Using yarn:

yarn add navscroll

Directly include it in html:

<script src="node_modules/navscroll/dist/navscroll.js"></script>

When including it in html, it will automatically call `Vue.use` and also set a `NavScroll` property on the window object that you can use !

Features

This package was inspired by two other great packages: vue-scrollactive and vue-scrollto.

  • Scroll to an element inside a given container (if you only need this feature, got to the usage section below)

  • Highlights navigation items as you scroll based on the current visible section inside the scrolling container

  • Keeps track of added/removed navigation items inside a given wrapper element with a smart DOM observer

  • Uses window.requestAnimationFrame to perform the animations for performance optimization.

  • Supports animation cancelation

  • Easing done with the outstanding bezier-easing micro-library

  • Fully customizable behavior like easing or scroll axis by passing a configuration object

  • Uses passive event listeners when possible for better performance

  • Uses vanilla JS !

Be sure to check the live demo !

Usage

NavScroll.js can be used either as a vue component, a vue directive or programatically from your javascript.

In your JS:

import NavScroll from 'navscroll';
Vue.use(NavScroll);

// This will register both a "navscroll" directive and component globally. You can rename as follow in your Vue instances:
new Vue({
  components: { 'new-name': NavScroll }
  // or
  directives: { 'new-name': NavScroll }
})

All options should be passed as a prop in the component, as binding value to the directive or as object when directly calling NavScroll methods.

Check out the Configuration section for more details about the available options.

You can set the defaults with

NavScroll.setDefaults({
    container: 'body',
    duration: 500,
    easing: 'ease',
    offset: 0,
    cancelable: true,
    onDone: false,
    onCancel: false,
    scrollX: false,
    scrollY: true
})

As a Vue Component

<navscroll class="nav-scroll-items"
      container="#my-scrollable-container"
      item-selector=".item"
      active-class="active-element">

      <a v-for="(entry,i) of entries" :key="i"
        :href="'#'+entry+'-target'"
        class="item">My nav item {{i}}</a>
</navscroll>

As a Vue Directive (on the wrapper)

<nav class="nav-scroll-items"
     v-navscroll:item="{
       container: '#my-scrollable-container',
       activeClass: 'active-element'
     }">

      <a v-for="(entry,i) of entries" :key="i"
        :href="'#'+entry+'-target'"
        class="item">My nav item {{i}}</a>
</nav>

As a Vue Directive (on the clickable navigation items)

<nav id="wrapper" ref="wrapper" class="nav-scroll-items">

      <a v-for="(entry,i) of entries" :key="i"
        :href="'#'+entry+'-target'"
        class="item"
        v-navscroll="{
          container: '#my-scrollable-container',
          activeClass: 'active-element'
        }">My nav item {{i}}</a>
</nav>

This will only attach the scrollTo function to the navigation items. If you also want the onScroll beahavior, then you have to explicitely call NavScroll.initObserver(this.$refs.wrapper, '.item', optionsObject) with the proper arguments (optionsObject would be the object passed as binding to the directives). NOTE: Be sure to call this function when both the navigation wrapper and the scrolling container are present in the DOM to properly register the handlers.

Programmatically

<nav id="wrapper" class="nav-scroll-items">

      <a v-for="(entry,i) of entries" :key="i"
        :href="'#'+entry+'-target'"
        class="item">My nav item {{i}}</a>
</nav>

And in the script:

let navWrapper = document.getElementById('wrapper');
let options = { container: '#my-scrollable-container', activeClass: 'active-element' }

// Call the following code when both the nav wrapper and the scrolling container are present in the DOM
// This will register the scrollTo fn as the onlick handler on the nav items and also register the onScroll handler on the scrolling container. It will then observe for new/removed nav items inside the wrapper.
NavScroll.initObserver(navWrapper, '.item', options)

// If you only want the scrollTo behavior on your nav items, do this instead:
[].slice.call(document.querySelectorAll('.item')).forEach(element => {
  let target = element.hash;
  let duration = 400;
  element.addEventListener('click', NavScroll.scrollTo.bind(null, target, duration, options))
})

// Another alternative
import NavScroll from 'navscroll';

var options = {
    container: '#my-scrollable-container',
    easing: 'ease-in',
    offset: 60,
    cancelable: true,
    onDone: function() {
      // scrolling is done
    },
    onCancel: function() {
      // scrolling has been cancelled
    },
    scrollX: false,
    scrollY: true
}

var cancelScroll = NavScroll.scrollTo(targetElement, duration, options)

// or alternatively inside your components you can use
cancelScroll = this.$scrollTo(targetElement, duration, options)

// to cancel scrolling you can call the returned function
cancelScroll()

You only need the scrollTo feature ?

If you only need the scrollTo feature just import the scroll-to.js script instead of the whole navscoll lib in your browser or module:

import ScrollTo from 'navcroll/dist/scroll-to'

or in html:

<script src="/node_modules/dist/navscroll/scroll-to.js"></script>

In browser environment, this will add the NavScrollTo function to the window object. The function has the following signature: NavScrollTo(targetElement, duration, options).

Configuration

All options are optional and have default values.

{
  /**
  * The scrollable container.
  * It can be a selector string or the HTML element itself
  *
  * @default 'body'
  * @type {String|HTMLElement}
  */
  container: 'body',
  /**
  * Selector that will be used to recognize the navigation items inside the navigation wrapper.
  *
  * @default  'scroll-item'
  * @type {String}
  */
  itemSelector: '.scroll-item',
  /**
  * Class that will be applied to the menu item after the scroll animation.
  *
  * @default  'active'
  * @type {String}
  */
  activeClass: 'active',
  /**
   * The target element/selector for the scrollTo method. Only used when registering
   * click handlers on the nav items. If the option is not set, registration will use
   * the href or the dataset.href of the registered nav item.
   * Alias: 'element'
   *
   * @default null
   * @type {String|HTMLElement}
   */
  el: null,
  /**
  * The duration of the scroll animation
  *
  * @default 600
  * @type {Number}
  */
  duration: 600,
  /**
  * Your custom easing value for the click to scroll functionality.
  * It must be:
  * - a string with 4 values separated by commas in a cubic bezier format (ex: '.5,0,.35,1').
  * - a string value among one of the following values:
  *       'ease', 'linear', 'ease-in', 'ease-out' or 'ease-in-out'
  * - an array of 4 values in a cubic bezier format (ex: [0.5, 0, 0.35, 1]).
  *
  * @example ".5,0,.35,1"
  * @default 'ease'
  * @type {String|Array}
  */
  easing: "ease",
  /**
  * Whether to scroll on the X axis
  *
  * @default false
  * @type {Boolean}
  */
  scrollX: false,
  /**
  * Whether to scroll on the Y axis
  *
  * @default true
  * @type {Boolean}
  */
  scrollY: true,
  /**
  * Amount of space between top / left side of screen and the section to
  * highlight.
  *
  * @default 0
  * @type {Number}
  */
  offset: 0,
  /**
  * Threshold amount of space between left side of screen and the section to
  * highlight as the current one (for the onScroll handler).
  *
  * @default (2/3 of the X axis of the screen, calculated each time onScroll is called). Here's the formula:
  * ```
  * Math.round(
  *   (window.innerWidth || document.documentElement.clientWidth) / 3
  * ) * 2
  * ```
  * @type {Number}
  */
  onScrollOffsetX: undefined,
  /**
  * Threshold amount of space between top side of screen and the section to
  * highlight as the current one (for the onScroll handler).
  *
  * @default (2/3 of the Y axis of the screen, calculated each time onScroll is called). Here's the formula:
  * ```
  * Math.round(
  *   (window.innerHeight || document.documentElement.clientHeight) / 3
  * ) * 2
  * ```
  * @type {Number}
  */
  onScrollOffsetY: undefined,
  /**
  * Defines whether to track section changes when
  * clicking an item to scroll to its section. If set to true,
  * the scrolling listener will always keep track and change the active class
  * to the current section while scrolling, if false, the scrolling handler will be
  * removed temporarily from the scrolling container and the active class will be
  * immediately applied to the clicked menu item, ignoring the passed sections
  * until the scrolling is over.
  *
  * @default false
  * @type {Boolean}
  */
  alwaysTrack: false,
  /**
  * Allow the scroll animation to be cancelled.
  * In that case, events like 'keyup' or 'touchmove' will cancel the animation
  * and scroll the content immediately to the target.
  *
  * @default 0
  * @type {Boolean}
  */
  cancelable: true,
  /**
  * Whether to stop the propagation of the click event on a menu item
  *
  * @default true
  * @type {Boolean}
  */
  stopPropagation: true,
  /**
  * Callback called when scrolling is finished.
  * Also called when the scroll animation is cancelled (right after the onCancel callback).
  *
  * @default null
  * @type {Function}
  */
  onDone: null,
  /**
  * Callback called when the scroll animation is cancelled.
  *
  * @default null
  * @type {Function}
  */
  onCancel: null,
  /**
  * Whether to update window.location.hash when a link menu item with a href is clicked
  *
  * @default true
  * @type {Boolean}
  */
  anchor: true,
  /**
  * Hash of the target section.
  * It will be applyed to window.location.hash if the `anchor` option is set to true.
  *
  * NOTE: If the clicked item or if the `clickedNavItem` option is set and the element has
  * a href or a data-href attribute, this attribute it will have priority to this option.
  *
  * @default null
  * @type {String}
  */
  hash: null,
  /**
  * Enables/disables the scrolling when clicking in a menu item.
  * Disable if you'd like to handle the scrolling by your own.
  *
  * @default true
  * @type {Boolean}
  */
  clickToScroll: true,
  /**
  * The reference to the navigation element that was clicked to trigger the scroll.
  *
  * @default null
  * @type {HTMLElement}
  */
  clickedNavItem: null,
  /**
  * An array of navigation elements that can be clicked to trigger
  * a scroll to their target section.
  *
  * @default []
  * @type {Array<HTMLElement>}
  */
  navItems: [],
}
Issues
  • SSR Support

    SSR Support

    Hi. Could SSR support be added using something like vue-scrollto did here?

    opened by davidbwaters 4
  • Scroll to is not working on Firefox

    Scroll to is not working on Firefox

    https://github.com/nash403/navscroll-js/blob/a93f0ef44ec623fc76aeaf8d8e97ea0ff9928a51/src/navscroll.js#L172

    Hi nash403!

    There should be const clickedElement = e.currentTarget;
    instead of const clickedElement = event.currentTarget;

    window.event is avalaible under Chrome\IE only.

    bug 
    opened by andykras 2
  • Scrolling the page doesn't add active class to menu item

    Scrolling the page doesn't add active class to menu item

    HiNash, tnx for the plugin, is amazing. I've go t a little issue with the page scrolling, in fact if i scroll the active class remain on the item i've clicked before.

    I'm using navscroll-js as a component in Vue.js this is my code in the template

    `<navscroll class="nav-scroll-items"
    			container="html"
    			item-selector=".item"
    			:alwaysTrack="navscroll.alwaysTrack"
            	:cancelable="navscroll.cancelable"
            	:scrollAxis="navscroll.scrollAxis"
    			:anchor="navscroll.anchor"
    			active-class="active-element">
    			<a 
    			  v-for="(entry,i) of navscroll.entries" 
    			  :key="i"
    			  :href="'#'+entry.id+'-target'"
    			  class="item"
    			  :data-text="entry.name">
    			  {{entry.name}}
    			</a>
    			<div class="navscroll-bg"></div>
    	</navscroll>`
    

    in data

    `navscroll: {
            anchor: false,
            alwaysTrack: false,
            cancelable: true,
            scrollAxis: 'y',
            el: 'section',
            entries: [{
              name: 'The dream',
              id: 'thedream'
            }, {
              name: 'Cars',
              id: 'cars'
            }, {
              name: 'Gallery',
              id: 'gallery'
            }, {
              name: '#zerouno',
              id: 'zerouno'
            }]
          },`
    

    Thanks a lot for your answer Cheers

    NND

    opened by na86 2
  • Update index.html

    Update index.html

    This seems to be mistype?

    opened by simon300000 1
  • Develop

    Develop

    opened by nash403 0
  • [Request] Window as scroll container

    [Request] Window as scroll container

    Would be great if the window could be used as the scroll container. Requiring to set a container so the inner contents will scroll is not optimal in some cases. vue-scrollactive allows use of a window container. Thanks.

    opened by levkarma 0
  • [REQUEST] Parent element to active

    [REQUEST] Parent element to active

    Would be great if there was an option that allowed us to trigger an item's parent to active as well. For example, when making collapsible navigation bars.

    opened by gustavoiha 0
  • [REQUEST] Element change event

    [REQUEST] Element change event

    Currently we can handle the animation events, but there's no way to know which element was changed. It would be great it was passed as an argument via an $emit.

    opened by gustavoiha 1
Owner
Honoré Nintunze
Web Engineer & Tech Lead (Freelance) - IT ninja who loves beer, sun & nice food 🚀 | #Nodejs #VueJS #vanillajs #opensource
Honoré Nintunze
Lightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.

vue-scrollactive This component makes it simple to highlight a menu item with an 'active' class as you scroll. Highlights items with a class as you sc

Mauricio Farias Dziedzinski 502 Nov 23, 2021
A Vue.js directive for body scroll locking without breaking scrolling of a target element.

v-scroll-lock A Vue.js directive for body scroll locking (for iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox) without breaking scrollin

Pete Hegman 173 Nov 9, 2021
A Vue.js directive for body scroll locking without breaking scrolling of a target element.

v-scroll-lock A Vue.js directive for body scroll locking (for iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox) without breaking scrollin

Pete Hegman 173 Nov 9, 2021
A Back-to-top component for Vue.js, which scroll page to the top when clicked

Vue Backtotop Component A Back-to-top component for Vue.js, which scroll page to the top when clicked Demo See demo. Install via npm npm install vue-b

Caio Fernandes 181 Nov 20, 2021
A Back-to-top component for Vue.js, which scroll page to the top when clicked

Vue Backtotop Component A Back-to-top component for Vue.js, which scroll page to the top when clicked Demo See demo. Install via npm npm install vue-b

Caio Fernandes 182 Nov 15, 2021
A reusable component for Vue 3 that renders a list with a huge number of items (e.g. 1000+ items) as a grid in a performant way.

A reusable component for Vue 3 that renders a list with a huge number of items (e.g. 1000+ items) as a grid in a performant way.

Roc Wong 42 Nov 22, 2021
A vue directive to make a scrollable element scroll by draging to the scroll direction

vue-dragscroll vue-dragscroll is a micro vue.js directive which enables scrolling via holding the mouse button ("drag and drop" or "click and hold" st

null 201 Oct 22, 2021
Component that customizes the scroll and inserts shadow when scrolling exists

Vue Scroll Shadow • • Component that customizes the scroll and inserts shadow when scrolling exists Installation NPM npm i vue-scroll-shadow # or yarn

André Lins 2 Oct 1, 2021
(🗃️ Archived) Vue 2 directive for custom scrollbar that uses native scroll behavior. Lightweight, performant, customizable and without dependencies. Used successfully in production on https://ggather.com

??️ Archived & No Longer Maintained I've decided to archive this library because my priorities changed a bit and I no longer have enough resources (ti

null 661 Nov 9, 2021
⌨️ A Safari browser extension, use keyboard control browser jumps, scrolling, switching tabs and more. support iPadOS and macOS

Support Keyboard Key Description k Scroll up j Scroll down u Fast scroll up d Fast scroll down h Scroll left l Scroll right f Highlight shift Open lin

Haojen 12 Nov 13, 2021
Scroll to page top button, Vue.js component.

vue-go-top Scroll to page top button, Vue.js component. Demo Demo Install Browser <script src="vue.js"></script> <script src="vue-go-top.min.js"></scr

null 29 Sep 5, 2021
🎉 Page scroll progress bar component for @vuejs

vue-scroll-progress ?? Simple Vue.js plugin for page scroll progress bar Live Demo Installation npm i vue-scroll-progress --save yarn add vue-scroll-p

Hyouk Seo 90 Oct 12, 2021
A managed scroller to dynamically load items

vue-managed-scroller View live demo in sandbox Installation npm install --save vue-managed-scroller or if you prefer yarn yarn add vue-managed-scroll

Justin Levine 16 Jul 21, 2021
Vue.js plugin for page scroll progress bar

vue-scroll-progress-bar Getting started Install $ npm install @guillaumebriday/vue-scroll-progress-bar --save or $ yarn add @guillaumebriday/vue-scrol

Guillaume Briday 81 Nov 23, 2021
Vue.js plugin for page scroll progress bar

vue-scroll-progress-bar Getting started Install $ npm install @guillaumebriday/vue-scroll-progress-bar --save or $ yarn add @guillaumebriday/vue-scrol

Guillaume Briday 80 Nov 6, 2021
A sigle-page scroll plugin based on [email protected],support for mobile and PC .

fullpage-vue A sigle-page scroll plugin based on [email protected],support for mobile and PC . 中文版 overview To achieve sigle-page scroll in mobile, support hori

abelTO 149 Sep 13, 2021
nuxt-fullpage is a nuxt module for creating fullscreen page scroll fast and simple.

Nuxt fullpage Nuxt module for creating fullscreen page scroll fast and simple. Demo online Table of contents Installation Usage Options Contributing I

Open Source Afghanistan 12 Nov 15, 2021
A tiny Vue directive that stop propagation scroll when edge reached

vue-scroll-stop A tiny Vue directive that stop propagation scroll when edge reached. Works with desktop mousewheel and mobile touchmove events ✅ On ❌

Volodymyr Antoniuk 42 Aug 2, 2021
Vue component that provides content scrolling and zooming using mouse events or two fingers pinch on a mobile devices

vue-pinch-scroll-zoom Vue component that provides content scrolling and zooming using mouse events or two fingers pinch on a mobile devices example: h

CoddiCat 6 Nov 22, 2021