Giter Site home page Giter Site logo

kimyvgy / simple-scrollspy Goto Github PK

View Code? Open in Web Editor NEW
78.0 4.0 22.0 175 KB

Simple scrollspy without jQuery, no dependencies

Home Page: https://kimyvgy.github.io/simple-scrollspy/

License: MIT License

JavaScript 10.02% TypeScript 89.98%
hacktoberfest scrollspy javascript scroll

simple-scrollspy's Introduction

Simple Scrollspy

NPM version

Simple scrollspy is a lightweight javascript library without jQuery, no dependencies. It is used to make scrollspy effect for your menu, table of contents, etc. Only 1.4Kb.

Examples:

Install

Using NPM package

Install NPM package - https://www.npmjs.com/package/simple-scrollspy:

npm install simple-scrollspy

Using CDNjs

The simple-scrollspy is already on CDNjs. Therefore, you can:

  1. Go to https://cdnjs.com/libraries/simple-scrollspy
  2. Choose a version
  3. Click Copy Script Tag, CDNjs will generate the script and copy them to your clipboard. For example:
<script src="https://cdnjs.cloudflare.com/ajax/libs/simple-scrollspy/2.4.1/simple-scrollspy.min.js" integrity="sha512-NNb5TgmE+7PHedvAWwPKZ/ukCGJciTHZ23ghPriEeEfcGySDBm9zIrjaXp/WNAUcVYhi5XhJ1rHveDKR35CInw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Using simple-scrollspy.min.js file

You can download simple-scrollspy.min.js file on each release. Please check the latest version.

<script src="/path/to/dist/simple-scrollspy.min.js"></script>

Usages

Easy for using, syntax just like this:

scrollSpy(menuElement, options)

This little plugin will add active class into your existing menu item when you scroll your page to a matched section by ID. If you are giving it a try, make sure that you:

  1. Added CSS for active class in your menu item. Because this plugin doesn't include CSS.
  2. Added ID for your sections. Example: <section id="first-section">...</section>
  3. Added an attribute which is a section ID into your menu items. The default value is href. Example: "href"="#first-section". You also replace href with the other name by hrefAttribute in options.

Arguments

  1. The menuElement is a query selector for your menu. It is String or HTMLElement instance.
  2. The options is optional. It types of Object contains the properties below:
Name Type Default Description
sectionClass String .scrollspy Query selector to your sections
menuActiveTarget String li > a Element will be added active class
offset Number 0 Offset number
hrefAttribute String href The menu item's attribute name which contains section ID
activeClass String active Active class name will be added into menuActiveTarget
scrollContainer String, HTMLElement window User Defined Scrolling Container
smoothScroll Boolean, Object false Enable the smooth scrolling feature
smoothScrollBehavior Function undefined Define your smooth scroll behavior
onActive Function undefined Trigger after the menu item is added the activeClass class

ES6 example

import scrollSpy from 'simple-scrollspy'

const options = {
  sectionClass: '.scrollspy',           // Query selector to your sections
  menuActiveTarget: '.menu-item',       // Query selector to your elements that will be added `active` class
  offset: 100,                          // Menu item will active before scroll to a matched section 100px
  scrollContainer: '.scroll-container', // Listen scroll behavior on `.scroll-container` instead of `window`
}

// init:
scrollSpy(document.getElementById('main-menu'), options)

// or shorter:
scrollSpy('#main-menu', options)

Inject static file

<script src="/path/to/dist/simple-scrollspy.min.js"></script>
<script>
  window.onload = function () {
    scrollSpy('#main-menu', {
      sectionClass: '.scrollspy',
      menuActiveTarget: '.menu-item',
      offset: 100,
      // smooth scroll
      smoothScroll: true,
      smoothScrollBehavior: function(element) {
        console.log('run "smoothScrollBehavior"...', element)
        element.scrollIntoView({ behavior: 'smooth' }) // default behavior
      }
    })
  }
</script>

Smooth scroll

import jumpTo from 'jump.js'

scrollSpy('#main-menu', {
  // ....,

  // enable smooth scroll:
  // - true: enable with the default scroll behavior
  // - false: disable this feature
  // - object: enable with some options that will pass to `Element.scrollIntoView` or `smoothScrollBehavior`
  //   + Default behavior: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
  //   + Jump.js: https://www.npmjs.com/package/jump.js
  smoothScroll: true,

  // customize scroll behavior,
  // - default: Element.scrollIntoView({ ...smoothScroll, behavior: 'smooth' })
  // - customize: you can define your scroll behavior. Ex: use `jump.js`, jQuery, .etc
  smoothScrollBehavior: function(element, options) {
    // use `jump.js` instead of the default scroll behavior
    jumpTo(element, {
      duration: 1000,
      offset: -100,
    })
  }
})

Development

$ yarn install
$ yarn dev

Build

$ yarn build

or:

$ npm run build

The dist folder is automatically created and includes the file simple-scrollspy.min.js

Note

  • Feel free to make a pull request if you can, and create a Github Issue if you come across one.
  • Don't forget to give it a star if you feel that the library is helpful to you. It may save somebody a lot of trouble someday.

Support / Donate

Helpful links

Licence

MIT

simple-scrollspy's People

Contributors

adnjoo avatar brunob avatar dependabot[bot] avatar jbardon avatar johnzanussi avatar kimyvgy avatar mrinmay7875 avatar renovate[bot] avatar robhuska avatar sulliops avatar thailt-2980 avatar vanquynguyen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

simple-scrollspy's Issues

[Feature]: Add hook `onActive`

import scrollSpy from 'simple-scrollspy'

scrollSpy('#main-menu', {
  sectionClass: '.scrollspy'
  menuActiveTarget: '.scrollspy-menu-item',
  offset: 100,

  // Add new hook
  onActive: (el: Element) => {
    console.log(['Trigger when the menu item is added the active class', el]);
  }
})

FR: Spport for matching window.location.pathname - so multi-page menus with section scroll

The code below was used with classic page nav.

    function setActiveUrl(navlinkClass, activeClass) {

        navlinkClass = navlinkClass || "nav-link";
        activeClass = activeClass || "active";

        var path = window.location.pathname;
        path = path.replace(/\/$/, "");
        path = decodeURIComponent(path);

        var navlinks = document.querySelectorAll(`.${navlinkClass}`);
        var activeNavlinks = document.querySelectorAll(`.${navlinkClass} .${activeClass}`);

        (activeNavlinks || []).forEach(e => {
            e.classList.remove(activeClass);
        });

        (navlinks || []).forEach(e => {
            var href = e.getAttribute("href");
            var isRootMatch = path == "" && href == "/";
            if (href == path || isRootMatch)
                e.classList.add(activeClass);
            
        });
    }

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm standard-version Available

Other Branches

These updates are pending. To force PRs open, click the checkbox below.

  • chore(deps): replace dependency standard-version with commit-and-tag-version ^9.1.1

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/cache v4
.github/workflows/publish.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/cache v4
npm
package.json
  • standard-version ^9.1.1
  • terser-webpack-plugin ^5.3.6
  • ts-loader ^9.5.1
  • typescript ^5.3.3
  • webpack ^5.76.0
  • webpack-cli ^5.0.0
  • jump.js ^1.0.2

  • Check this box to trigger a request for Renovate to run again on this repository

Feature Request: User Defined Scrolling Container

Allow the user to target other containers that scroll other than the body. I have pulled the master and made some modifications myself, but they are pretty janky and could be done cleaner by the main developer.

refactor: adding a smooth scroll

Hey man, it's a great script, and it seems to work very well. I would suggest adding a smooth scroll though, because it really gives the viewer a sense of what is going on instead of just checking the browser scrollbar.

Active class always on `a` tag even with menuActiveTarget targeting parent tag

Hi, event if i set menuActiveTarget to li element containing the a item of my menu the active class is set to the a and not the li. Maybe i've misunderstood the usage this param ?

I see that menuActiveTarget is used in removeCurrentActive() but not in setActive(), maybe that's the origine of the bug ?

My code is based on the demo file, adapted like that :

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Simple Scrollspy</title>
  <link rel="stylesheet" href="demo.css">
</head>
<body>
<div class="app">
  <nav class="navbar">
    <div class="container">
      <div class="navbar-brand">
        <h1>
          <a href="">Simple Scrollspy</a>
        </h1>
      </div>

      <div class="menu" id="main-menu">
        <ul>
          <li><a href="#hero">Hero</a></li>
          <li><a href="#section-1">Section 1</a></li>
          <li><a href="#section-2">Section 2</a></li>
          <li><a href="#section-3">Section 3</a></li>
          <li><a href="#section-4">Section 4</a></li>
       </ul>
      </div>
    </div>
  </nav>

  <section class="section scrollspy" id="hero">Hero</section>
  <section class="section scrollspy" id="section-1">Section 1</section>
  <section class="section scrollspy" id="section-2">Section 2</section>
  <section class="section scrollspy" id="section-3">Section 3</section>
  <section class="section scrollspy" id="section-4">Section 4</section>

  <footer class="footer">
    <div class="container">
      <p>
        <a href="https://github.com/huukimit/simple-scrollspy" title="Fork me on Github">
          Simple Scrollspy - Github
        </a>
      </p>
    </div>
  </footer>
</div>

<script async src="dist/simple-scrollspy.min.js"></script>
<script defer>
  window.onload = function () {
    scrollSpy('#main-menu ul', {
      sectionClass: '.scrollspy',
      menuActiveTarget: 'li',
      offset: 100,
      // scrollContainer: null,
      // smooth scroll
      smoothScroll: true,
      smoothScrollBehavior: function(element) {
        console.log('run "smoothScrollBehavior"...', element)
        element.scrollIntoView({ behavior: 'smooth' })
      },
      onActive: (el) => {
        console.log('run "onActive"...', el);
        console.log(el.parentNode);
      }
    })
  }
</script>
</body>
</html>

2 times on the same page

Hi,

Is it possible to use the function 2 times (cf. 2 different places/list) on the same page ?

Refactor: Add throttle for the scroll event handler

When scrolling fast, the scroll event handler is called too many times. Therefore, the activeClass adds / removes to every the menu items.

Expect: Only add activeClass 1 time for the menu item when scrolling stopped.

Click not working

Hello.
Thanks for the plugin.

But there is a problem.

import scrollSpy from "simple-scrollspy";
import jump from "jump.js";

const options = {
  sectionClass: ".section",
  menuActiveTarget: ".sticky__link",
  activeClass: "sticky__link-active",
  offset: 100,
  smoothScroll: true,
  smoothScrollBehavior: function (element, options) {
    // use `jump.js` instead of the default scroll behavior
    jump(element, {
      duration: 300,
      offset: -100,
    });
  },
};

scrollSpy("#sticky", options);

After the click, the anchor event fires: http://localhost:4000/#section_01

It turns out that it does not enter the onClick event.
I hope there is a solution. Thank you.

Version 2.5.0 breaks implementation with headings

We are using scrollspy on a sidebar navigation.
The sectionClass option is set to the class of the h2 and h3 headings in the content.

This was working fine until v2.4.2, but is now broken in v2.5.0.
See the following videos. Watch the red active links in the right sidebar:

2.4.2
https://d.pr/v/h7hzXc
The nav item remains active until the next one comes into view.

2.5.0
https://d.pr/v/N6YXfL
The nav item now only remains active very shortly. The active class is removed right after the heading is scrolled by.

This is unusable for us like this. I guess the fixes in the new implementation now need an actual encompassing section element, which we don't have in the content.

Not sure if you'd consider this a bug or if we were just lucky this worked for headings too before.

If this cannot be fixed, would it be an idea to add an option to make this work again?
Otherwise we'll need to stay on 2.4.2.

It's a bit disappointing that this new issue seems to be caused by fixing a bug I added in #29 in 2021.

error when trying to install the package via jsdelivr

Hi, I am using jsdelivr to install the package. This has worked perfectly so far and ran up to version 2.4.2 without any problems. With version 2.5.0, however, the package can no longer be installed in this way.

Please have a look:

2.4.2 works: https://cdn.jsdelivr.net/npm/[email protected]/+esm
2.5.0 doesn't: https://cdn.jsdelivr.net/npm/[email protected]/+esm

The following error appears:

/**
 * Failed to bundle using Rollup v2.79.1: failed to resolve an internal import.
 * If you believe this to be an issue with jsDelivr, and not with the package itself, please open an issue at https://github.com/jsdelivr/jsdelivr
 */

Any clue on how to get that work? Thanks in advance!

Horizontal Scrollspy

Hello, is there a possibility to detect sections through a horizontal axis and not vertical? I tried to change the values "Top" and "height" by "left" and "width" on the JS file without success. Thank you.

Sticky position issue

When some of the sectionClass elements have position: sticky, activeClass is not added to them when scrolling

Remove "dist" folder and package-lock.json

The "dist" folder will make conflict. It need to be stored as attachment on specify release version.

  1. Remove dist folder
  2. Update instruction in README.md
  3. Attach dist files into Release

Feature Request: Progress Mode

An option to turn on a "Progress Mode" in which the activeClass is applied as to the menuActiveTarget, but stays as you continue to scroll down. The catch would be to have it also remove the activeClass from a section as the user scrolls back up.

I hope this makes sense...

Here is a quick screencast of what I am talking about. This was achieved with advanced CSS rather than the script adding and removing the activeClass from every element.

https://www.youtube.com/watch?v=avSDfLesRZo&feature=youtu.be

Feature request: remove active class on first item in nav, when scrolled back up

Currently, when scrolling down, active classes are added and removed. Then scrolling back up, the last item (first in the nav) keeps its active class, even if the correponding section is way past it.

This looks confusing, especially in a page where the content + nav are a bit lower, e.g. below a large hero section.
When you scroll back up, and the section is way low, the first item still keeps its active class.

Undocumented necessity: data-scrollspy attribute

While trying to get the Bootstrap scrollspy plugin to work with a list of anchors with no ordered or unordered lists, I came across this little plugin. Gave it a try but to no avail. But I kept playing with it and discovered an undocumented necessity.

For the elements (tabs) that will be given the "active" class when scrolling takes place, they all need the "data-scrollspy="#[desired_value]"" attribute. It functions as an href attribute on an anchor; its value must correspond to the value of an element's id on the page. Without this attribute, this plugin won't work at all.

Somehow this necessary attribute isn't documented. I discovered it while studying the html of the example. Things worked perfectly once I added it to my page.

Hope this helps.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.