Skip to content

Many Scroller

A simple and easy to use scroller

Source Code

Installation

Since our @manyone packages are private on npmjs you must authenticate to install it with npm login.

If you’re not part of the Manyone organisation on npmjs.com, reach out to Caroline, Patrik or Lau.

pnpm add @manyone/animation

Getting started

Add Many Scroller to your project

Import and add the Many scroller to your index.html in the bottom of the markup

index.html
<w-many-scroller></w-many-scroller>
<script >
import { WManyScroller } from '@manyone/animation';
customElements.define('w-many-scroller', WManyScroller);
</script>
Create a global Many Scroller setup file
your-location/useManyScrollerOptions.ts
import { OptionRoot } from '@manyone/animation';
// Create your setups
const fadeInObj: OptionRoot = {
enter: {
type: 'progress',
distance: [0.5],
},
};
// Stringify your setups
const fadeIn = JSON.stringify(fadeInObj, null, 2);
// Export your setups to make them accessible in components
export const useManyScrollerOptions = () => {
return { fadeIn };
};
Use your setup in a component
yourComponent.astro
---
import {useManyScrollerOptions} from "@/yourLocation/useManyScrollerOptions";
const { fadeIn } = useManyScrollerOptions();
---
<div class="comp-enter-fade" data-many-scroller={fadeIn}>
<h1>Fade in on enter</h1>
</div>
<style lang="scss">
.comp-enter-fade {
opacity: calc(var(--scroll-position-enter) * 1);
}
</style>

Go to examples

Animating in CSS

You are able to animate with CSS forwards animations and dynamic CSS variable values.

Forwards

Forwards animations are used as inview trigger animations with fixed duration.

CSS forwards animations are also great for hero intro animations, when the animation is done it’ll keep the styles from the last keyframe.

.component {
&.inview-screen {
animate: example 1s ease-in forwards;
}
}
@keyframes example {
from {opacity: 0}
to {opacity: 1}
}

Progress variables

Progress variables is used to hook your animation into scroll positions

// Animates the component from opacity 0 to 1 based on the distance
.component {
opacity: calc(1 * var(--scroll-position-enter));
}

Debug message

The debug message is created to easier navigate and iterate your values with designers while creating the page. It’ll create a sticky debug element, with values used in your Many Scroller setup on the specific component.

Its a good idea to use the debug message for faster developing.

<w-many-scroller debug="true"></w-many-scroller>

Option values

Option values are all the different types of values you are able to use while setting up your Many Scroller setup.

Types

inview

Everytime element is in view add .inview-(scrollerType) and remove the class when out of view.

inview-once

First time element is in view add .inview-(scrollerType).

progress

Everytime element is in view add .inview-(scrollerType) and remove the class when out of view.

Adds a dynamic scroll position variable to the element in percentage as a value from 0 to 1.

Numbers

distance and offsets

Numbers are a percentage of screen height.

[1] = 100% of screen height

[0.5] = 50% of screen height

[0] = 0% of screen height

breakpoints

Minimim window width in pixels

Event types

Progress

Fires events on scroll, while inview

Enter

Fires one event every time the element enters view

Enter-once

Fires one event first time the element enters view

Exit

Fires one event every time the element leaves view

Exit-once

Fires one event first time the element leaves view

Scroller types

There are 4 different scroll types: full, screen, enter and exit. Select the ones you feel suits your needs the best.

You are able to add multiple scroll types to one Many Scroller setup, if you want an enter animation and parallax etc.

Full

Full is using the entire screen height plus the height of the element. Its great for parallax, heros and sticky components.

Setup
const exampleObj: OptionRoot = {
full: {
type: // "inview" || "inview-once" || "progress"
}
};
const example = JSON.stringify(exampleObj, null, 2);
Usage
.inview-full {
// Do something inview
// Availble on all types
}
Options
PropertiesData typeValuesDefault Value
typeString
  • inview
  • inview-once
  • progress
inview-once
offsetStartArray of Numbers
  • [Number, Number]
[0]
offsetEndArray of Numbers
  • [Number, Number]
[0]
eventArray of Strings
  • progress
  • enter
  • enter-once
  • exit
  • exit-once
False

Screen

Screen is only related to screen height. Its great for animations needed to be done at an exact point on the users screen and triggering events; like highlighting a subnavigation when the content enters 25% of screen visibility.

Setup
const exampleObj: OptionRoot = {
screen: {
type: // "inview" || "inview-once" || "progress"
}
};
const example = JSON.stringify(exampleObj, null, 2);
Usage
.inview-screen {
// Do something inview
// Availble on all types
}
Options
PropertiesData typeValuesDefault Value
typeString
  • inview
  • inview-once
  • progress
inview-once
distanceArray of Numbers
  • [Number, Number]
[0]
offsetStartArray of Numbers
  • [Number, Number]
[0]
eventArray of Strings
  • progress
  • enter
  • enter-once
  • exit
  • exit-once
False

Enter

Enter is used when a object is entering the viewport. Its great for component enter animations like Fade In, Background color change etc.

Setup
const exampleObj: OptionRoot = {
enter: {
type: // "inview" || "inview-once" || "progress"
}
};
const example = JSON.stringify(exampleObj, null, 2);
Usage
.inview-enter {
// Do something inview
// Availble on all types
}
Options
PropertiesData typeValuesDefault Value
typeString
  • inview
  • inview-once
  • progress
inview-once
distanceArray of Numbers
  • [Number, Number]
[0]
eventArray of Strings
  • progress
  • enter
  • enter-once
  • exit
  • exit-once
False

Exit

Exit is used when a object is leaving the viewport. Its great for component exit animations like Fade Out.

Setup
const exampleObj: OptionRoot = {
exit: {
type: // "inview" || "inview-once" || "progress"
}
};
const example = JSON.stringify(exampleObj, null, 2);
Usage
.inview-exit {
// Do something inview
// Availble on all types
}
Options
PropertiesData typeValuesDefault Value
typeString
  • inview
  • inview-once
  • progress
inview-once
distanceArray of Numbers
  • [Number, Number]
[0]
eventArray of Strings
  • progress
  • enter
  • enter-once
  • exit
  • exit-once
False

Events

Events are used to trigger functions and acts like an observer. You can use it for highlighting subnavigations when enteringer or leaving content, trigger Spline animations etc.

The amount of event callbacks is decided by the type of event you choose, see the event options, on the scroller type you’ve selected.

Setup
const exampleObj: OptionRoot = {
full: {
type: 'progress',
event: ['progress'],
},
};
const example = JSON.stringify(exampleObj, null, 2);

Create the event ID in your markup, its used for callbacks

Note: All events needs to be unique, so include an unique id like __iud from Storyblok.

yourComponent.astro
<div
data-many-scroller="{example}"
data-many-scroller-event-id="example-{__uid}"
>
<!-- Your content -->
</div>
Usage
yourComponent.astro
// scrollerType = "full", in this example
document.addEventListener('example-{__uid}-{scrollerType}-{eventType}', (event) => {
// In this example the event.detail will follow your CSS variable and return a number between 0-1.
myProgressFunction(event.detail);
// If you dont want to fire the event all the time use one of the other options and just trigger the function
myFunction();
});

Remember to destroy your eventListener when switching page

Breakpoints

You are able to use breakpoints in pixels based on screen width. This allows you the change distances and/or offsets for mobile/tablet/desktop.

If you have more breakpoints than distance/offsets values, it’ll use the last availble value.

NOTE: Don’t add breakpoints if you are not changing your distance/offset values.

Setup
const exampleObj: OptionRoot = {
breakpoints: [320, 1024],
full: {
type: 'progress',
offsetEnd: [0.5],
offsetStart: [0.5, 0.25],
},
};
const example = JSON.stringify(exampleObj, null, 2);

Scroll direction

Scroll direction is default in Many Scroller. It can be used to show/hide navigation while scrolling up or down.

Usage

The scroll direction is set on the html-tag as a data attribute

[data-scrolldir='down'] {
& nav {
// Your CSS
}
}
[data-scrolldir='up'] {
& nav {
// Your CSS
}
}

Examples

Here is some inspiration

[CSS-Forwards] Inview cards

See the example here.

const exampleObj: OptionRoot = {
screen: {
type: 'inview-once',
offsetStart: [0.75],
distance: [0.25],
},
};
const example = JSON.stringify(exampleObj, null, 2);

[CSS-Progress] Enter and exit fade

See the example here.

const exampleObj: OptionRoot = {
enter: {
type: 'progress',
distance: [0.5],
},
exit: {
type: 'progress',
distance: [0.25],
},
};
const example = JSON.stringify(exampleObj, null, 2);

[CSS-Progress] Parallax (Example: 1)

See the example here.

const exampleObj: OptionRoot = {
full: {
type: 'progress',
},
};
const example = JSON.stringify(exampleObj, null, 2);

[CSS-Progress] Parallax (Example: 2)

See the example here.

const exampleObj: OptionRoot = {
enter: {
type: 'progress',
distance: [0.75],
},
screen: {
type: 'progress',
distance: [0.25],
offsetStart: [0.25],
},
};
const example = JSON.stringify(exampleObj, null, 2);

[CSS-Progress] Horisontal scroll

See the example here.

const exampleObj: OptionRoot = {
full: {
type: 'progress',
offsetEnd: [1],
offsetStart: [1],
},
};
const example = JSON.stringify(exampleObj, null, 2);

[Event] Enter and exit canvas event

See the example here.

const exampleObj: OptionRoot = {
full: {
type: 'progress',
event: ['enter', 'exit'],
},
};
const example = JSON.stringify(exampleObj, null, 2);

[Event] Progress Canvas

See the example here.

const exampleObj: OptionRoot = {
full: {
type: 'progress',
event: ['progress','enter', 'exit'],
},
};
const example = JSON.stringify(exampleObj, null, 2);