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

varscroll

v2.1.0

Published

Standalone parallax scrolling for mobile and desktop with CSS variables

Downloads

28

Readme

varScroll

This started as a Fork of a great basicScroll library made by electerious, but it is heavily modified to accomodate velocity (check stiffness, dampening), handle adding/removing css classes, using percentage (%) as start/end and simplifiing api.

Standalone parallax scrolling for mobile and desktop with CSS variables.

varScroll allows you to change CSS variables depending on the scroll position. Use the variables directly in your CSS to animate whatever you want. Highly inspired by skrollr and Reactive Animations with CSS Variables.

Contents

Features

  • Framework independent
  • Insane performance
  • Support for mobile and desktop
  • CommonJS and AMD support
  • Simple JS API

Setup

We recommend installing varScroll using npm or yarn.

npm install varscroll
yarn add varscroll

Include the JS file at the end of your body tag…

<script src="dist/varScroll.min.js"></script>

...or using cdn

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/varScroll.min.js"></script>

…or skip the JS file and use varScroll as a module:

const varScroll = require('varscroll')
import { create } as varScroll from 'varscroll'

onMount(() => {
	const instance = create({
		elem: domElement,
		'--opacity': {
			from: '0',
			to: '1',
			start: '0%',
			end: '100%',
			stiffness: 0.1,
			damping: 0.25
		}
	});

	instance.start();
	instance.update();

	return () => {
		instance.stop();
		instance.destroy();
	};
});

Usage

This demo shows how to change the opacity of an element when the user scrolls. The element starts to fade as soon as the top of the element reaches the bottom of the viewport. An opacity of .99 is reached when the middle of the element is in the middle of the viewport.

Tip: Animating from .01 to .99 avoids the repaints that normally occur when the element changes from fully transparent to translucent and from translucent to fully visible.

const instance = varScroll.create({
    elem: document.querySelector('.element'),
    '--opacity': {
        start: '0%',
        end: '100%',
        from: .01,
        to: .99,
        stiffness: 0.1,
        damping: 1,
        inside: (instance, percentage, props) => {
            console.log('inside', percentage, props);
        },
        outside: (instance, percentage, props) => {
            console.log('outside', percentage, props);
        },
        insideClass: 'inside-class',
        outsideClass: 'outside-class',
        enterClass: 'enter-class',
        leaveClass: 'leave-class',
    },
    '--rotate': [
        {
            start: '0%',
            end: '20%',
            from: '0deg',
            to: '180deg',
        },
        {
            start: '80%',
            end: '0%',
            from: '180deg',
            to: '0deg',
        }
    ]
})

instance.start()
.element {
    /*
     * Use the same CSS variable as specified in our instance.
     */
    opacity: var(--opacity);
    /*
     * The will-change CSS property provides a way for authors to hint browsers about the kind of changes
     * to be expected on an element, so that the browser can setup appropriate optimizations ahead of time
     * before the element is actually changed.
     */
    will-change: opacity;
}

API

.create(data)

Creates a new varScroll instance.

Be sure to assign your instance to a variable. Using your instance, you can…

  • …start and stop the animation.
  • …check if the instance is active.
  • …get the current props.
  • …recalculate the props when the window size changes.

Examples:

const instance = varScroll.create({
    elem: document.querySelector('.element'),
    '--opacity': {
        start: '0%',
        end: '100%',
        from: 0,
        to: 1
    }
})
const instance = varScroll.create({
    elem: document.querySelector('.element'),
    '--translateY': {
        start: '0%',
        end: '100%',
        from: '0',
        to: '100%',
        timing: 'elasticOut'
    }
})
const instance = varScroll.create({
    elem: document.querySelector('.element'),
    inside: (instance, percentage, props) => {
        console.log('viewport is inside start and end')
    },
    outside: (instance, percentage, props) => {
        console.log('viewport is outside start and end')
    },
    '--rotate': {
        start: '50%',
        end: '100%',
        from: "0deg",
        to: "360deg"
    }
})

Parameters:

  • data {Object} An object of data.

Returns:

  • {Object} The created instance.

Instance API

Each varScroll instance has a handful of handy functions. Below are all of them along with a short description.

.start()

Starts to animate the instance. varScroll will track the scroll position and adjust the props of the instance accordingly. An update will be performed only when the scroll position has changed.

Example:

instance.start()

.stop()

Stops to animate the instance. All props of the instance will keep their last value.

Example:

instance.stop()

.destroy()

Destroys the instance. Should be called when the instance is no longer needed. All props of the instance will keep their last value.

Example:

instance.destroy()

.update()

Triggers an update of an instance, even when the instance is currently stopped.

Example:

const props = instance.update()

Returns:

  • {Object} Applied props.

.calculate()

Converts the start and end positions of the instance to absolute values. varScroll relies on those values to start and stop the animation at the right position. It runs the calculation once during the instance creation. .calculate() should be called when elements have altered their position or when the size of the site/viewport has changed.

Example:

instance.calculate()

.isActive()

Returns true when the instance is started and false when the instance is stopped.

Example:

instance.isActive()

Returns:

  • {Boolean}

.getData()

Returns calculated data. More or less a parsed version of the data used for the instance creation. The data might change when calling the calculate function.

Example:

instance.getData()

Returns:

  • {Object} Parsed data.

Data

The data object can include the following properties:

{
    /*
     * DOM element/node.
     */
    elem: null,
    /*
     * Start and stop position.
     */
    start: null,
    end: null,
    /*
    * Spring Params
    */
    stiffness: 0.1,
    damping: 1,
    /*
     * Direct mode.
     */
    direct: false,
    /*
     * Track window size changes.
     */
    track: true,
    /*
     * Callback functions.
     */
    inside: (instance, percentage, props) => {},
    outside: (instance, percentage, props) => {},
    /*
     * Classes for state changes.
     */
    insideClass: '',
    outsideClass: '',
    enterClass: '',
    leaveClass: '',
    /*
     * Props.
     */
    '--name': {
        /*
         * Start and end values.
         */
        from: null,
        to: null,
        /*
         * Animation timing.
         */
        timing: 'ease'
    }
}

DOM element/node

Type: Node Default: null Optional: true

A DOM element/node.

The position and size of the element will be used to convert the start and end positions to absolute values. How else is varScroll supposed to know when to start and stop an animation with relative values?

You can skip the property when using absolute values.

Example:

{
    elem: document.querySelector('.element')
    /* ... */
}

Start and end positions

Type: Integer|String Default: null Optional: false

varScroll starts to animate the props when the scroll position is above start and below end. Absolute and relative values are allowed.

Relative values require a DOM element/node. The first part of the value describes the element position, the last part describes the viewport position: <element>-<viewport>. middle-bottom in start specifies that the animation starts when the middle of the element reaches the bottom of the viewport.

Known relative values: top-top, top-middle, top-bottom, middle-top, middle-middle, middle-bottom, bottom-top, bottom-middle, bottom-bottom

It's possible to track a custom anchor when you want to animate for a specific viewport height or when you need to [start and end with

an offset](https://github.com/electerious/basicScroll/issues/17#issuecomment-449134650).

Examples:

{
    /* ... */
    start: '0px',
    end: '100px',
    /* ... */
}
{
    /* ... */
    start: '0%',
    end: '100%',
    /* ... */
}
{
    /* ... */
    start: 'top-middle',
    end: 'bottom-middle',
    /* ... */
}

Direct mode

Type: Boolean|Node Default: false Optional: true

varScroll applies all props globally by default. This way you can use variables everywhere in your CSS, even when the instance tracks just one element. Set direct to true or to a DOM element/node to apply all props directly to the DOM element/node or to the DOM element/node you have specified. This also allows you to animate CSS properties, not just CSS variables.

  • false: Apply props globally (default)
  • true: Apply props to the DOM element/node
  • Node: Apply props to a DOM element/node of your choice

Examples:

<!-- direct: false -->
<html style="--name: 0;">
    <div class="trackedElem"></div>
    <div class="anotherElem"></div>
</html>
<!-- direct: true -->
<html>
    <div class="trackedElem" style="--name: 0;"></div>
    <div class="anotherElem"></div>
</html>
<!-- direct: document.querySelector('.anotherElem') -->
<html>
    <div class="trackedElem"></div>
    <div class="anotherElem" style="--name: 0;"></div>
</html>

Track window size changes

Type: Boolean Default: true Optional: true

varScroll automatically recalculates and updates instances when the size of the window changes. You can disable the tracking for each instance individually when you want to take care of it by yourself.

Note: varScroll only tracks the window size. You still must recalculate and update your instances manually when you modify your site. Each modification that changes the layout of the page should trigger such an update in your code.

Example:

const instance = varScroll.create({
    elem: document.querySelector('.element'),
    start: 'top-bottom',
    end: 'bottom-top',
    track: false,
    '--opacity': {
        from: 0,
        to: 1
    }
})

// Recalculate and update your instance manually when the tracking is disabled.
// Debounce this function in production to avoid unnecessary calculations.
window.onresize = function() {
    instance.calculate()
    instance.update()
}

Callback functions

Type: Function Default: () => {} Optional: true

Both callbacks receive the current instance, a percentage and the calculated properties:

  • < 0% percent = Scroll position is below start
  • = 0% percent = Scroll position is start
  • = 100% percent = Scroll position is end
  • > 100% percent = Scroll position is above end

Example:

{
    /* ... */
    inside: (instance, percentage, props) => {},
    outside: (instance, percentage, props) => {},
    /* ... */
}

Classes for state changes

Type: String Default: '' Optional: true

  • insideClass: Class to add while the element is inside the start and end range.
  • outsideClass: Class to add while the element is outside the start and end range.
  • enterClass: Class to add once the element enters the start and end range (not automatically removed).
  • leaveClass: Class to add once the element leaves the start and end range (not automatically removed).

Example:

{
    /* ... */
    '--opacity': {
        from: 0,
        to: 1,
        insideClass: 'inside',
        outsideClass: 'outside',
        enterClass: 'entered',
        leaveClass: 'left'
    }
}

Props

Type: Object Default: {} Optional: true

Values to animate when the scroll position changes.

Each prop of the object represents a CSS property or CSS Custom Property (CSS variables). Custom CSS properties always start with two dashes. A prop with the name --name is accessible with var(--name) in CSS.

More about CSS custom properties.

Example:

{
    /* ... */
    '--one-variable': { /* ... */ },
    '--another-variable': { /* ... */ }
}

Start and end values

Type: Integer|String Default: null Optional: false

Works with all kinds of units. varScroll uses the unit of to when from has no unit.

Examples:

'--name': {
    /* ... */
    from: '0',
    to: '100px',
    /* ... */
}
'--name': {
    /* ... */
    from: '50%',
    to: '100%',
    /* ... */
}
'--name': {
    /* ... */
    from: '0',
    to: '1turn',
    /* ... */
}

Animation timing

Type: String|Function Default: linear Optional: true

Examples:

const easeInOutQuad = (t) => {
    return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
};

'--name': {
    /* ... */
    timing: 'easeInOutQuad'
}
'--name': {
    /* ... */
    timing: (t) => t * t
}

Tips

  • Only animate transform and opacity and use will-change to hint browsers about the kind of changes. This way the browser can setup appropriate optimizations ahead of time before the element is actually changed.
  • Keep the amount of instances low. More instances means more checks, calculations and style changes.
  • Don't animate everything at once and don't animate too many properties. Browsers don't like this.
  • Smooth animations by adding a short transition to the element: transform: translateY(var(--ty)); transition: transform .1s.
  • varScroll applies all props globally by default. Try to reuse variables across elements instead of creating more instances.