Skip to content

ryanwalters/sticky-events

Repository files navigation

Sticky Events

Events for position: sticky, without the need for an onscroll listener.

Installation

$ npm install sticky-events

Browser support

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
No IE / Edge 16+ 55+ 56+ 12.1+ 43+

A Polyfill for IntersectionObserver is available here.

Options

Option Name Type Default Description
container Element or Document document The element that contains your sticky elements. Grabs all sticky elements on the page by default.
enabled boolean true Enable sticky events immediately.
stickySelector string .sticky-events The selector to use to find your sticky elements within container.

Events

The StickyEvents class has constants we can use to listen for events.

Event Name Description
StickyEvents.CHANGE Fired when an element becomes stuck or unstuck
StickyEvents.STUCK Fired only when an element becomes stuck
StickyEvents.UNSTUCK Fired only when an element becomes unstuck

When an event is fired, the following data is available from the event.detail property:

{
  isSticky: Boolean,
  position: StickyEvents.POSITION_BOTTOM|StickyEvents.POSITION_TOP,
}

Methods

Method Name Arguments Description
addSticky Node or Element Add a single sticky to the existing set of stickies
addStickies NodeList or array Add a list of stickies to the existing set of stickies
disableEvents boolean Stop firing events on the set of stickies. By default, this will fire a StickyEvents.UNSTUCK event on the sticky elements, resetting them to their original state. Pass false to leave the stickies alone.
enableEvents none Start firing events on the set of stickies

How to use

Given the following HTML:

<div class="my-sticky-container">
    <div>
        <h2 class="custom-sticky-selector">Sticky Heading 1</h2>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </div>
    <div>
        <h2 class="custom-sticky-selector">Sticky Heading 2</h2>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </div>
    <div>
        <h2 class="custom-sticky-selector">Sticky Heading 3</h2>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    </div>
</div>

We could configure StickyEvents like this:

import StickyEvents from 'sticky-events';


// Create new StickyEvents instance

const stickyEvents = new StickyEvents({
  container: document.querySelector('.my-sticky-container'),
  enabled: false,
  stickySelector: '.custom-sticky-selector'
});


// Enable events

stickyEvents.enableEvents();


// Add event listeners

const { stickyElements, stickySelector } = stickyEvents;

stickyElements.forEach(sticky => {
  sticky.addEventListener(StickyEvents.CHANGE, (event) => {
    sticky.classList.toggle('bg-dark', event.detail.isSticky);
  });
});


// Add stickies at some point after initialization

fetch('/api/gimme-divs')
  .then(response => response.text())
  .then(html => letsPretendToCreateADocument(html))
  .then((document) => {
    const stickies = document.querySelectorAll(stickySelector);

    stickies.forEach(sticky => {
      sticky.addEventListener(StickyEvents.CHANGE, (event) => {
        sticky.classList.toggle('bg-dark', event.detail.isSticky);
      });
    });  

    stickyEvents.addStickies(stickies);
  });

// Disable events

stickyEvents.disableEvents();