• Stars
    star
    3,633
  • Rank 11,699 (Top 0.3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Standalone parallax scrolling for mobile and desktop with CSS variables.

basicScroll

Donate via PayPal

Standalone parallax scrolling for mobile and desktop with CSS variables.

basicScroll 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

Demos

Name Description Link Author
Default Includes most features Try it on CodePen
Callback Animate properties in JS via callbacks Try it on CodePen
Parallax scene A composition of multiple, moving layers Try it on CodePen @electerious
Rolling eyes Custom element to track scrolling Try it on CodePen @electerious
Headline explosion Animated letters Try it on CodePen @electerious
Scroll and morph Morph text using CSS clip-path Try it on CodePen @mikaelainalem
Parallax with JS Several examples and a debug mode Try it on CodePen AnimatiCSS

Tutorials

Name Link
πŸ“ƒ Parallax scrolling with JS controlled CSS variables Read it on Medium
🎬 Apple-like scroll animations Watch it on YouTube
🎬 Parallax effect tutorial (πŸ‡ͺπŸ‡Έ) Watch it on YouTube

Features

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

Requirements

basicScroll depends on the following browser features and APIs:

Some of these APIs are capable of being polyfilled in older browsers. Check the linked resources above to determine if you must polyfill to achieve your desired level of browser support.

Setup

We recommend installing basicScroll using npm or yarn.

npm install basicscroll
yarn add basicscroll

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

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

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

const basicScroll = require('basicscroll')
import * as basicScroll from 'basicscroll'

Usage

This demo shows how to 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. A 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 = basicScroll.create({
	elem: document.querySelector('.element'),
	from: 'top-bottom',
	to: 'middle-middle',
	props: {
		'--opacity': {
			from: .01,
			to: .99
		}
	}
})

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(html, opts)

Creates a new basicScroll 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 = basicScroll.create({
	from: '0',
	to: '100px',
	props: {
		'--opacity': {
			from: 0,
			to: 1
		}
	}
})
const instance = basicScroll.create({
	elem: document.querySelector('.element'),
	from: 'top-bottom',
	to: 'bottom-top',
	props: {
		'--translateY': {
			from: '0',
			to: '100%',
			timing: 'elasticOut'
		}
	}
})
const instance = basicScroll.create({
	elem: document.querySelector('.element'),
	from: 'top-middle',
	to: 'bottom-middle',
	inside: (instance, percentage, props) => {
		console.log('viewport is inside from and to')
	},
	outside: (instance, percentage, props) => {
		console.log('viewport is outside from and to')
	}
})

Parameters:

  • data {Object} An object of data.

Returns:

  • {Object} The created instance.

Instance API

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

.start()

Starts to animate the instance. basicScroll 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 stop position of the instance to absolute values. basicScroll 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.
	 */
	from: null,
 	to: null,
	/*
	 * Direct mode.
	 */
	direct: false,
	/*
	 * Track window size changes.
	 */
	track: true,
	/*
	 * Callback functions.
	 */
	inside: (instance, percentage, props) => {},
	outside: (instance, percentage, props) => {},
	/*
	 * Props.
	 */
	props: {
		/*
		 * Property name / CSS Custom Properties.
		 */
		'--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 stop position to absolute values. How else is basicScroll 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 stop position

Type: Integer|String Default: null Optional: false

basicScroll starts to animate the props when the scroll position is above from and below to. 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 from 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.

Examples:

{
	/* ... */
	from: '0px',
	to: '100px',
	/* ... */
}
{
	/* ... */
	from: 0,
	to: 360,
	/* ... */
}
{
	/* ... */
	from: 'top-middle',
	to: 'bottom-middle',
	/* ... */
}

Direct mode

Type: Boolean|Node Default: false Optional: true

basicScroll 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

basicScroll 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: basicScroll 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 = basicScroll.create({
	elem: document.querySelector('.element'),
	from: 'top-bottom',
	to: 'bottom-top',
	track: false,
	props: {
		'--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 from
  • = 0% percent = Scroll position is from
  • = 100% percent = Scroll position is to
  • > 100% percent = Scroll position is above from

Example:

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

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:

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

Start and end values

Type: Integer|String Default: null Optional: false

Works with all kinds of units. basicScroll 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

A known timing or a custom function. Easing functions get just one argument, which is a value between 0 and 1 (the percentage of how much of the animation is done). The function should return a value between 0 and 1 as well, but for some timings a value less than 0 or greater than 1 is just fine.

Known timings: backInOut, backIn, backOut, bounceInOut, bounceIn, bounceOut, circInOut, circIn, circOut, cubicInOut, cubicIn, cubicOut, elasticInOut, elasticIn, elasticOut, expoInOut, expoIn, expoOut, linear, quadInOut, quadIn, quadOut, quartInOut, quartIn, quartOut, quintInOut, quintIn, quintOut, sineInOut, sineIn, sineOut

Examples:

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

Related

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.
  • basicScroll applies all props globally by default. Try to reuse variables across elements instead of creating more instances.

More Repositories

1

Lychee

A great looking and easy-to-use photo-management-system you can run on your server, to manage and share photos.
PHP
6,312
star
2

Ackee

Self-hosted, Node.js based analytics tool for those who care about privacy.
JavaScript
4,121
star
3

formbase

Better default styles for common input elements.
SCSS
567
star
4

basicLightbox

The lightest lightbox ever made.
JavaScript
532
star
5

basicModal

Easy-to-use dialog system for modern web-apps.
JavaScript
283
star
6

ackee-tracker

Transfer data to Ackee.
JavaScript
190
star
7

basicContext

Easy-to-use context-menu for your website or webapp.
JavaScript
168
star
8

Rosid

Just-in-time development server and static site generator.
JavaScript
143
star
9

nice-try

Tries to execute a function and discards any error that occurs.
JavaScript
66
star
10

basicGrid

A Foundation-like grid system based on the flex display property.
SCSS
56
star
11

basicSlider

A slider in its purest form.
JavaScript
33
star
12

scrollSnap

Section-based scrolling for your site.
JavaScript
27
star
13

fsify

Convert an array of objects into a persistent or temporary directory structure.
JavaScript
26
star
14

Skeleton-Components

A front-end Malvid template build upon Rosid.
CSS
24
star
15

use-ackee

Use Ackee in React.
JavaScript
23
star
16

basicRotate

Rotate throw a set of 360 degree images using your mouse or finger.
JavaScript
20
star
17

ackee-bitbar

Ackee stats in your macOS menu bar.
JavaScript
16
star
18

ackee-lighthouse

Send Lighthouse reports to Ackee.
JavaScript
13
star
19

Skeleton-EJS

A front-end template build upon Rosid.
CSS
13
star
20

basicPlaceholder

Easy-to-use persistent placeholders for input fields.
JavaScript
10
star
21

basicNotification

Easy-to-use notification-system for your website or webapp.
CoffeeScript
9
star
22

basicPaginate

Paginate a NodeList like there's no tomorrow.
JavaScript
9
star
23

limit-number

Limit a number between a min and max value.
JavaScript
7
star
24

zbarimg

Scan photos using ZBar in Node.js.
CoffeeScript
6
star
25

dribbble-2x

Safari extension for Dribbble, which always shows the @2x version.
JavaScript
6
star
26

rosid-handler-sass

Load SCSS and transform to CSS, add vendor prefixes and minify.
JavaScript
6
star
27

basicTasks

A collection of gulp-tasks used in personal projects.
JavaScript
5
star
28

rosid-handler-twig

Load Twig templates and render them.
JavaScript
5
star
29

Feedboard

Design your feed.
JavaScript
5
star
30

Skeleton-NJK

A front-end template build upon Rosid.
CSS
5
star
31

key-value-replace

Replace key/value pairs in a string.
JavaScript
5
star
32

rosid-handler-ejs

Load EJS templates and render them.
JavaScript
5
star
33

lychee-watermark

Adds a second watermarked photo when uploading images to Lychee.
PHP
5
star
34

require-data

Extracts data out of multiple file types.
JavaScript
5
star
35

lychee-redirect

Redirect from an album-name to a Lychee-album.
PHP
5
star
36

rename-extension

Changes the the extension of a given filename or path.
JavaScript
5
star
37

rosid-handler-njk

Load Nunjucks templates and render them.
JavaScript
4
star
38

rosid-handler-js

Load, transform, bundle and compress JS.
JavaScript
4
star
39

basicFit

Turn elements on your site into a responsive unified grid.
CoffeeScript
4
star
40

rosid-handler-node

Load JS and transform to HTML.
JavaScript
3
star
41

count-between

Counts up and down between two numbers.
JavaScript
3
star
42

ausgabe

Tiny logger with zero defaults.
JavaScript
3
star
43

modulizer

Wrap this snippets around your code to support CommonJS, AMD and non-module-definitions.
JavaScript
3
star
44

eslint-config

ESLint configuration for my personal projects.
JavaScript
2
star
45

pdfconcat

Concat multiple pdfs using pdfunite in Node.js.
CoffeeScript
2
star
46

continuous-stealthy-require

Requires a fresh, uncached module without causing a memory leak.
JavaScript
2
star
47

ackee-faker

Fills Ackee with fake data.
JavaScript
2
star
48

Ackee-Netlify-Test-Instance

JavaScript
1
star
49

rosid-handler-js-next

Load, transform, bundle and compress modern JS.
JavaScript
1
star
50

Skeleton-React

A front-end template build upon Rosid.
JavaScript
1
star
51

vh-variable

TypeScript
1
star