npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@morev/smooth-scroll

v1.0.0

Published

The last script for animated scrolling you ever need

Downloads

44

Readme

@morev/smooth-scroll (still WIP)

Stability of "master" branch License: MIT Last commit Release version GitHub Release Date Keywords

The last script for animated scrolling you ever need.

Table of contents

Installation

Using yarn:

yarn add @morev/smooth-scroll

Using npm:

npm install @morev/smooth-scroll

Using pnpm

pnpm add @morev/smooth-scroll

Usage

There are two modules you can use: smooth-scroll and smooth-scroll-native.

smooth-scroll

Uses the window.requestAnimationFrame.

ES modules

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll({/* custom options */});
scroll.to('#target-element');

CommonJS

const { SmoothScroll } = require('@morev/smooth-scroll');

const scroll = new SmoothScroll({/* custom options */});
scroll.to('#target-element');

Browser

<script src="smooth-scroll/dist/smooth-scroll.umd.js"></script>
<script>
  const scroll = new SmoothScroll({/* custom options */});
  scroll.to('#target-element');
</script>

smooth-scroll-native

Uses the native scrollTo method with behavior: smooth.

ES modules

import { SmoothScrollNative } from '@morev/smooth-scroll/native';

const scroll = new SmoothScrollNative({/* custom options */});
scroll.to('#target-element');

CommonJS

const { SmoothScrollNative } = require('@morev/smooth-scroll/native');

const scroll = new SmoothScrollNative({/* custom options */});
scroll.to('#target-element');

Browser

<script src="smooth-scroll/dist/smooth-scroll-native.js"></script>
<script>
  const scroll = new SmoothScrollNative({/* custom options */});
  scroll.to('#target-element');
</script>

Vue.js

import SmoothScroll from '@morev/smooth-scroll/vue';

Vue.use(SmoothScroll, {/* custom options */});
<template>
  <button @click="scrollTo"></button>
</template>

<script>
  export default {
    methods: {
      scrollTo() {
        this.$SmoothScroll.to('#target-element');
      },
    },
  };
</script>

Vue module creates the only instance, so if you need multiple instances, you should use SmoothScroll directly.

Options

element

{
  element: HTMLElement | Window | 'auto;
}

The element being scrolled, window object, or auto for getting the nearest scrollable ancestor element.

Default value: auto.

The value auto is suitable in most cases, but sometimes it may cause some unexpected behavior, mostly in scenarios involving fixed elements and/or not unique selectors.
It also does not affects if scroll target is a certain value rather than element.
So it is recommended to set this option explicitly, and maybe to have separated instances to process the page and inner blocks scrolling.

duration

{
  duration: number | [number, number];
}

Scroll animation duration.

This is the number representing the amount of time in milliseconds that it should take to scroll 1000px. The greater the distance, the longer the animation will take (twice as much for 2000px, three times more for 3000px, etc.).

There can also be supplied an array of two values which first value is duration and second value is duration limit. By default, the limit is 2000ms.

Does not affects while using smooth-scroll-native.

Default value: [300, 700].

easing

{
  easing: (time: number, begin: number, change: number, duration: number) => number;
}

The easing function used during the scroll animation.
Can be one of js-easing-functions (included as dependency).
See the example "Custom animation".

Does not affects while using smooth-scroll-native.

Default value: imported easeInOutQuad function.

ifNeeded

{
  ifNeeded: boolean;
}

Whether to not invoke scrolling if target position is already in viewport.

Default value: false.

autofocus

{
  autofocus: boolean;
}

Whether to set focus to the target element after scrolling.
Affects only if a given target is an element/selector.

Default value: false.

It is strongly recommended to set this option to true, at least while navigating through the page.

block

{
  block: 'start' | 'end' | 'center';
}

Alignment of the target element after scrolling by x-axis.
Affects only if a given target is an element/selector.

Default value: start.

inline

{
  inline: 'start' | 'end' | 'center';
}

Alignment of the target element after scrolling by y-axis.
Affects only if a given target is an element/selector.

Default value: start.

offset

{
  offset: number | { x: number; y: number; };
}

Additional offset(-s) added to the result position values.
Single value treats as Y-axis offset, with object notation can set X and Y offsets both. Affects only if a given target is an element/selector.

offset.x

Additional offset added to the result x-axis position value.

Default value: 0.

offset.y

Additional offset added to the result y-axis position value.

Default value: 0.

fixedElements

{
  fixedElements: {
    x: {
      start: Array<HTMLElement | string>;
      end: Array<HTMLElement | string>;
    };
    y: {
      start: Array<HTMLElement | string>;
      end: Array<HTMLElement | string>;
    };
  };
}

A set of HTML elements (or its selectors) whose sizes should be considered in the result position calculation.
Affects only if a given target is an element/selector.

fixedElements.x.start

An array of elements whose sizes should be excluded from the result x-axis position value.

Default value: [].

fixedElements.x.end

An array of elements whose sizes should be included to the result x-axis position value.

Default value: [].

fixedElements.y.start

An array of elements whose sizes should be excluded from the result y-axis position value.

Default value: [].

fixedElements.y.end

An array of elements whose sizes should be included to the result y-axis position value.

Default value: [].

API

to

Smoothly scrolls to a given target.

Arguments:

| Name | Type | Default | Description | |---------|------------------------------------------|---------|-----------------------------------------------------------------------------------------------------| | target* | number\|number[]]\|HTMLElement\|string | — | A number (y-value), an array of two numbers (x and y values), HTML element or the element selector. | | options | object | {} | Custom options, extends the initial options for current invocation. |

Returns:

Promise<number[]> - Promise object representing the array of result x and y scroll position.

Example:

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll();

scroll.to(1000);
scroll.to([0, 1000]);
scroll.to(document.querySelector('#target-element'));
scroll.to('#target-element');
scroll.to('#target-element', {/* override the initial options */});

addFixedElements

Dynamically adds fixed elements after initialization.

Arguments:

| Name | Type | Default | Description | |------------|----------------------------|---------|-----------------------------------------------------------------------------------------| | axis* | string | — | Whether to add the elements to the x or y category of fixedElements option. | | alignment* | string | — | Whether to add the elements to the start or end category of fixedElements option. | | elements* | ...(HTMLElement\|string) | — | The elements being added. |

Returns:

SmoothScroll - The class instance.

Example:

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll();
scroll.addFixedElements('y', 'start', '.element-one', document.querySelector('.element-two'), '.element-three');

removeFixedElements

Dynamically removes registered fixed elements.

Arguments:

| Name | Type | Default | Description | |-----------|----------------------------|---------|-----------------------------| | elements* | ...(HTMLElement\|string) | — | The elements being removed. |

Returns:

SmoothScroll - The class instance.

Example:

import { SmoothScroll } from 'smooth-scroll';

const scroll = new SmoothScroll({
  fixedElements: {
    y: {
      start: [
        document.querySelector('.element-one'),
        'element-two',
      ],
    },
  },
});

scroll.removeFixedElements('.element-one', document.querySelector('.element-two'));

If one element is used in different categories of the fixedElements option, it will be removed everywhere.

Recipes

Sticky navigation with anchor links

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll({
  autofocus: true,
  fixedElements: {
    y: {
      start: ['#sticky-nav.is-fixed'],
    },
  },
});

document.addEventListener('click', (e) => {
  const link = e.target.closest('#sticky-nav .anchor-link');
  if (!link) return;

  scroll.to(link.hash);
  e.preventDefault();
});

Custom animation

import { SmoothScroll } from '@morev/smooth-scroll';
import { easeInQuad } from '@morev/smooth-scroll/easing';

const scroll = new SmoothScroll({
  duration: 600,
  easing: easeInQuad,
});

scroll.to('#target-element');

Fixed scroll animation duration

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll({
  duration: [600, 600], // animation will always take exactly the same amount of time
});

scroll.to('#target-element');

Reduced motion mode

import { SmoothScroll } from '@morev/smooth-scroll';

const isMotionless = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const scroll = new SmoothScroll({
  duration: isMotionless ? 0 : 400,
});

scroll.to('#target-element');

Autofocus on the specific element

import { SmoothScroll } from '@morev/smooth-scroll';

const scroll = new SmoothScroll();
const target = document.querySelector('#target-element');

scroll.to(target).then(() => {
  const needFocus = target.querySelector('.need-focus');
  needFocus.focus();
});