Checkpoint
Animate elements on scroll.
Demos
Built-In Animations
Use the built-in animations.
<div class="box js-checkpoint" data-checkpoint-animation="fade-in">
fade-in
</div>
<div class="box js-checkpoint" data-checkpoint-animation="fade-up">
fade-up
</div>
<div class="box js-checkpoint" data-checkpoint-animation="fade-down">
fade-down
</div>
<div class="box js-checkpoint" data-checkpoint-animation="fade-left">
fade-left
</div>
<div class="box js-checkpoint" data-checkpoint-animation="fade-right">
fade-right
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-in">
zoom-in
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-in-up">
zoom-in-up
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-in-down">
zoom-in-down
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-in-left">
zoom-in-left
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-in-right">
zoom-in-right
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-out">
zoom-out
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-out-up">
zoom-out-up
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-out-down">
zoom-out-down
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-out-left">
zoom-out-left
</div>
<div class="box js-checkpoint" data-checkpoint-animation="zoom-out-right">
zoom-in-right
</div>
<div class="box js-checkpoint" data-checkpoint-animation="flip-up">
flip-up
</div>
<div class="box js-checkpoint" data-checkpoint-animation="flip-down">
flip-down
</div>
<div class="box js-checkpoint" data-checkpoint-animation="flip-left">
flip-left
</div>
<div class="box js-checkpoint" data-checkpoint-animation="flip-right">
flip-right
</div>
<div class="marker"></div>
import { CheckPoint, Utils } from 'formstone';
Utils.ready(() => {
CheckPoint.construct('.js-checkpoint', {
offset: '25%',
reverse: true,
});
});
body {
padding-bottom: 30vh;
}
body::before {
align-items: center;
content: 'Scroll Down\A\21E3';
display: flex;
height: 105vh;
justify-content: center;
text-align: center;
white-space: pre-wrap;
}
.box {
background: var(--color-yellow);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 0 auto 30vh;
padding: 20px 10px;
text-align: center;
width: 200px;
}
.marker {
width: 100%;
height: 0;
position: fixed;
bottom: 25vh;
border: 1px dashed var(--color-blue);
}
.marker::before {
position: absolute;
bottom: calc(100% + 10px);
left: 10px;
color: var(--color-blue);
content: 'offset: 25%';
text-transform: uppercase;
font-size: 14px;
line-height: 1;
}
Custom Animation
Define a custom animation.
<div class="box js-checkpoint" data-checkpoint-animation="spinner">
spinner
</div>
<div class="marker"></div>
import { CheckPoint, Utils } from 'formstone';
Utils.ready(() => {
CheckPoint.construct('.js-checkpoint', {
offset: '25%',
reverse: true,
});
});
.fs-checkpoint[data-checkpoint-animation="spinner"] {
--opacity: 0;
--transform: translate(0, 100%) scale(0.5) rotate(300deg);
--duration: 0.5s;
--ease: cubic-bezier(0.47, 1.64, 0.41, 0.8);
opacity: var(--opacity);
transform: var(--transform);
transition:
opacity var(--duration) linear,
transform var(--duration) var(--ease);
}
.fs-checkpoint[data-checkpoint-animation="spinner"].fs-checkpoint-active {
--opacity: 1;
--transform: translate(0, 0) scale(1) rotate(0deg);
}
body {
padding-bottom: 30vh;
}
body::before {
align-items: center;
content: 'Scroll Down\A\21E3';
display: flex;
height: 105vh;
justify-content: center;
text-align: center;
white-space: pre-wrap;
}
.box {
background: var(--color-yellow);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 0 auto 30vh;
width: 200px;
padding: 20px 10px;
text-align: center;
}
.marker {
width: 100%;
height: 0;
position: fixed;
bottom: 25vh;
border: 1px dashed var(--color-blue);
}
.marker::before {
position: absolute;
bottom: calc(100% + 10px);
left: 10px;
color: var(--color-blue);
content: 'offset: 25%';
text-transform: uppercase;
font-size: 14px;
line-height: 1;
}
Trigger
Set an element to act as the animation trigger.
<div class="container">
<div class="box js-checkpoint" data-checkpoint-trigger=".trigger" data-checkpoint-animation="trigger">
trigger
</div>
<div class="trigger">
Scroll Trigger
</div>
</div>
<div class="marker"></div>
import { CheckPoint, Utils } from 'formstone';
Utils.ready(() => {
CheckPoint.construct('.js-checkpoint', {
offset: '25%',
reverse: true,
});
});
body {
background: var(--color-gray-5);
}
body::before {
align-items: center;
content: 'Scroll Down\A\21E3';
display: flex;
height: 85vh;
justify-content: center;
text-align: center;
white-space: pre-wrap;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
border-radius: var(--border-size);
padding: 10vh;
}
.trigger {
align-self: flex-end;
background: var(--color-blue);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 80vh auto;
padding: 5px 10px;
text-align: center;
width: 200px;
}
.box {
position: sticky;
top: 50vh;
align-self: flex-start;
background: var(--color-white);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 0 auto;
width: 200px;
padding: 20px 10px;
text-align: center;
transform: translate(0, -50%);
}
.box.fs-checkpoint-active {
background: var(--color-yellow);
}
.marker {
width: 100%;
height: 0;
position: fixed;
bottom: 25vh;
border: 1px dashed var(--color-blue);
}
.marker::before {
position: absolute;
bottom: calc(100% + 10px);
left: 10px;
color: var(--color-blue);
content: 'offset: 25%';
text-transform: uppercase;
font-size: 14px;
line-height: 1;
}
Container
Set a container to animate elements inside a parent.
<div class="container">
<div class="box js-checkpoint" data-checkpoint-container=".container" data-checkpoint-animation="fade-in">
fade-up
</div>
</div>
<div class="marker"></div>
import { CheckPoint, Utils } from 'formstone';
Utils.ready(() => {
CheckPoint.construct('.js-checkpoint', {
offset: '75%',
reverse: true,
});
});
body {
background: var(--color-gray-5);
padding-bottom: 60vh;
}
body::before {
align-items: center;
content: 'Scroll Down\A\21E3';
display: flex;
height: 85vh;
justify-content: center;
text-align: center;
white-space: pre-wrap;
}
.container {
display: flex;
align-items: flex-end;
height: 50vh;
margin: 0 10vh 10vh;
background: var(--color-white);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
}
.box {
background: var(--color-yellow);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 0 auto 20px;
width: 200px;
padding: 20px 10px;
text-align: center;
}
.marker {
width: 100%;
height: 0;
position: fixed;
bottom: 75vh;
border: 1px dashed var(--color-blue);
}
.marker::before {
position: absolute;
bottom: calc(100% + 10px);
left: 10px;
color: var(--color-blue);
content: 'offset: 75%';
text-transform: uppercase;
font-size: 14px;
line-height: 1;
}
Parent
Set a container to animate elements inside a scrollable parent.
<div class="parent_wrapper">
<div class="parent">
<div class="box js-checkpoint" data-checkpoint-parent=".parent" data-checkpoint-animation="fade-in">
fade-up
</div>
<div class="marker"></div>
</div>
</div>
import { CheckPoint, Utils } from 'formstone';
Utils.ready(() => {
CheckPoint.construct('.js-checkpoint', {
offset: '25%',
reverse: true,
});
});
body {
background: var(--color-gray-5);
padding-bottom: 30vh;
}
body::before,
.parent::before {
align-items: center;
content: 'Scroll Down\A\21E3';
display: flex;
height: 85vh;
justify-content: center;
text-align: center;
white-space: pre-wrap;
}
body::before {
height: 75vh;
}
.parent {
overflow-y: scroll;
height: 80vh;
margin: 10vh;
background: var(--color-white);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
padding-bottom: 30vh;
}
.parent_wrapper {
position: relative;
}
.box {
background: var(--color-yellow);
border: var(--border-size) solid var(--color-black);
border-radius: var(--border-size);
margin: 0 auto 30vh;
width: 200px;
padding: 20px 10px;
text-align: center;
}
.marker {
width: calc(100% - 20vh - 4px);
height: 0;
position: absolute;
bottom: 25%;
border: 1px dashed var(--color-blue);
}
.marker::before {
position: absolute;
bottom: calc(100% + 10px);
left: 10px;
color: var(--color-blue);
content: 'offset: 25%';
text-transform: uppercase;
font-size: 14px;
line-height: 1;
}
Options
Set instance options by passing a valid object at initialization, or to the public .defaults() method. Custom options for a specific instance can also be set by attaching a data-checkpoint-options attribute containing a properly formatted JSON object to the target element.
| Name | Type | Default | Description |
|---|---|---|---|
offset |
string |
'0px' |
Element offset for activating animation (pixels or percentage) |
reverse |
boolean |
false |
Deactivate animation when scrolling back |
Data attributes provide additional configuration options and can be set directly on the target element.
| Name | Type | Description |
|---|---|---|
data-checkpoint-options |
string (JSON) |
JSON encoded object containing instance options |
data-checkpoint-animation |
string |
Animation type (e.g., fade-in, zoom-in-up, flip-left) |
data-checkpoint-offset |
string |
Custom offset value, overrides the option (pixels or percentage) |
data-checkpoint-parent |
string |
Selector for a scrollable parent container |
data-checkpoint-trigger |
string |
Selector for a custom trigger element |
data-checkpoint-container |
string |
Selector for parent trigger element |
Methods
Methods are publicly available to all active instances, unless otherwise stated.
| Name | Description |
|---|---|
.construct() |
Initializes CheckPoint on target elements |
.defaults() |
Sets default options for future CheckPoint instances |
.destroy() |
Removes instance and all related data |
.enable() |
Enables the CheckPoint instance |
.disable() |
Disables the CheckPoint instance |
.activate() |
Activates the checkpoint animation |
.deactivate() |
Deactivates the checkpoint animation |
.construct()
Initializes CheckPoint on target elements.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
selector |
string (required) |
'' |
Selector string to target |
options |
object (optional) |
{} |
Object containing instance options |
Returns
| Type | Description |
|---|---|
NodeList |
NodeList of target elements |
Examples
let targets = CheckPoint.construct('.js-checkpoint');
let targets = CheckPoint.construct('.js-checkpoint', {
reverse: true
});
.defaults()
Sets default options for future CheckPoint instances.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
options |
object (required) |
{} |
Object containing default options |
Examples
CheckPoint.defaults({
reverse: true
});
.destroy()
Removes instance and all related data.
Examples
el.CheckPoint.destroy();
.enable()
Enables the CheckPoint instance.
Examples
el.CheckPoint.enable();
.disable()
Disables the CheckPoint instance.
Examples
el.CheckPoint.disable();
.activate()
Activates the checkpoint animation.
Examples
el.CheckPoint.activate();
.deactivate()
Deactivates the checkpoint animation.
Examples
el.CheckPoint.deactivate();
Events
Events are triggered on the target instance's element, unless otherwise stated.
| Name | Description |
|---|---|
checkpoint:activate |
Checkpoint animation activated |
checkpoint:deactivate |
Checkpoint animation deactivated |
Styles
CSS custom properties are used to modify default styles.
| Property | Default | Description |
|---|---|---|
--fs-checkpoint-duration |
0.5s |
Transition duration (all animations) |
--fs-checkpoint-distance |
50px |
Translate distance (fade, zoom) |
--fs-checkpoint-perspective |
3000px |
Perspective value (flip) |
--fs-checkpoint-rotate |
90deg |
Rotation amount (flip) |
--fs-checkpoint-scale-in |
0.5 |
Scale amount (zoom-in) |
--fs-checkpoint-scale-out |
1.25 |
Scale amount (zoom-out) |
Classes allow deeper customization and indicate the current state of a specific instance.
| Classname | Type | Description |
|---|---|---|
.fs-checkpoint |
element |
Target element |
.fs-checkpoint-active |
modifier |
Indicates active state |
Animation styles only apply to .fs-checkpoint[data-checkpoint-animation]. .fs-checkpoint is added by CheckPoint when an instance is enabled (never add it to markup) and removed by .disable() and .destroy(), so elements stay visible without JavaScript and after an instance is disabled or destroyed. Elements already in view when CheckPoint initializes appear without an entrance animation. Custom animations should use the same selector, as in the demo above.