What is ScrollOut?
ScrollOut is a JavaScript microlibrary that detects scroll/resize changes in the browser and assigns attributes and live CSS Variables to the scrolling element and a list of targets.
The ScrollOut library does not handle any animation, but it gives you the elements and tools needed to create animations & transitions with JavaScript animation libraries or only CSS!
The general flow is:
- Decorate your targets with
data-scroll
attribute - Call ScrollOut() from JavaScript
- Each
data-scroll
is set to in or out when it comes in or goes out of view - As the element scrolls, it flips in and out
- Enable
cssProps
in the configuration to add live CSS Variables - Animate those elements with CSS or JavaScript!
Getting Started
Installing from a CDN
Include the following script in the head of your document
<script src="https://unpkg.com/scroll-out/dist/scroll-out.min.js"></script>
On document load/ready or in a script at the bottom the of the <body>
, do the following:
ScrollOut({
/* options */
});
Installing from NPM
Install scroll-out from NPM:
npm i scroll-out -S
Then import ScrollOut from the package and call it
import ScrollOut from "scroll-out";
ScrollOut({
/* options */
});
Compatibility
ScrollOut is compatible with all modern browsers and Internet Explorer. CSS Custom Properties are available to browsers that support CSS Variables (~85% of the current browser market share).
If you experience an issue with a browser that is prior to IE11, please create an issue so we can look at adding support.
Also, there is a well known Edge bug that may prevent transitions from firing properly. This should not be a problem when Edge Chromium is more widely used.
Tips (How do I?...)
Perform a Fade In with CSS
Add this to your css.
[data-scroll] {
transition: opacity 1s;
}
[data-scroll="in"] {
opacity: 1;
}
[data-scroll="out"] {
opacity: 0;
}
Add this to your page to select all elements with data-scroll
on them.
<script>
ScrollOut();
</script>
Perform a Fade with JavaScript
ScrollOut({
onShown: function(el) {
// use the web animation API
el.animate([{ opacity: 0 }, { opacity: 1 }], 1000);
},
onHidden: function(el) {
// hide the element initially
el.style.opacity = 0;
}
});
Use it with Animate.css
When using Animate.css, you can trigger animations by adding the animated
class.
ScrollOut({
onShown(el) {
el.classList.add("animated");
}
});
Force Animate.css Replay
When using animate.css, you may need to force the animation to play a second time. Luckily there is a handy way to force the browser to reflow the document and replay the animation:
ScrollOut({
onShown: function(el) {
// remove the class
el.classList.remove("animated");
// force reflow
void el.offsetWidth;
// re-add the animated cl
el.classList.add("animated");
}
});
This code sample uses the Web Animation API (Available on Chrome and FireFox). The general idea works for any animation library.
Target a Scroll Container
To use a scrolling pane other than the window, provide a scrollingElement as a css selector or an element.
ScrollOut({
scrollingElement: ".scrollable-pane"
});
Create a Sticky Header
The following example shows how to create a sticky header with ScrollOut.
<html>
<head>
<style>
.hero {
height: 400px;
}
.header {
position: relative;
height: 100px;
}
.sticky-header {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100px;
}
.sticky-header[data-scroll="in"] {
position: fixed;
}
</style>
</head>
<body>
<div class="hero"></div>
<div class="header">
<div class="sticky-header">HEADER</div>
</div>
<script>
ScrollOut({
targets: ".sticky-header",
offset: 400
});
</script>
</body>
</html>
Use with Frameworks
Most JS frameworks have setup/teardown methods that should be used when using ScrollOut.
Vue
export default {
mounted() {
this.so = ScrollOut({
scope: this.$el
});
},
destroyed() {
this.so.teardown();
}
};
Angular
@Component(/**/)
export class MyComponent implements AfterContentInit, OnDestroy {
so: any;
constructor(private el: ElementRef) {}
ngAfterContentInit() {
this.so = ScrollOut({
scope: this.el.nativeElement
});
}
ngOnDestroy() {
this.so.teardown();
}
}
I'm having trouble
Don't panic! Here are some common issues that can prevent ScrollOut from working correctly:
- Missing
<!DOCTYPE html>
or the browser is working in quirks mode. One of the biggest symptoms of this isdata-scroll="in"
anddata-scroll="out"
being reversed. Ensure the browser is not operating in quirks mode by having the proper DOCTYPE declaration. - The
scrollingElement
is not provided toScrollOut
and thedocument.scrollingElement
is not the container that is actually scrolling. If your code is settingoverflow
to something other than the body/html element, it needs to be passed toScrollOut
asscrollingElement
.
What's New?
- v2.2.10 - In this release, offset and threshold have been improved to accept a function instead of just a number. Performance was improved and intermitent first render issues have been fixed.
- v2.2.2 - Checkout this CodePen post to read about
--scroll-percent-x/y
,--viewport-x/y
, and changes tocssProps
- v2.0.0 - Checkout this CodePen post for all the exciting new features in 2.0.0
API
Configuration
Options | Description |
---|---|
cssProps | If true , all CSS Variables will be added to the scrolling element and all targets. If false , only the [data-scroll] property will be modified on targets. For more control, see CSS Props Options |
offset | The targets become visible when they reach this distance in pixels from the top of the screen. Setting this option overrides all other collision detection. This can also be a function that returns a number. |
once | Elements will only be changed from scroll-out to scroll-in once. This is useful if you want to transition all elements exactly once. The default value is false. |
scope | Use this is specify the root element to use when resolving targets. If not specified, the scrollingElement is used. |
scrollingElement | The scrolling container. When scope is not specified, it is assumed that all targets are children of this element. If not specified, the documentElement is used. |
targets | An optional list of elements or a css selector. By default, this is [data-scroll] |
threshold | The ratio of the element that must be visible before it is marked as visible. Providing the value 0.2 would require 20% of the element to be visible before marking it visible. This can also be a function that returns a number. |
Special options on Elements
The following attributes can be added to elements to enable options:
- scrollout-once: add this to enable the once option for a single element
Events
Event Handlers
The following event handlers can be added to the ScrollOut constructor:
ScrollOut({
onShown: function(element, ctx, scrollingElement) {
/* Triggered when an element is shown */
},
onHidden: function(element, ctx, scrollingElement) {
/* Triggered when an element is hidden */
},
onChange: function(element, ctx, scrollingElement) {
/* Triggered when an element changes visibility */
}
});
Event Context (ctx)
The following context object is passed to each of the event handlers.
Property | Description |
---|---|
offsetX | The distance from the left of the scrolling element |
offsetY | The distance from the top of the scrolling element |
elementWidth | The width of the element |
elementHeight | The height of the element |
index | The index of the element vs other targets being tracked by ScrollOut. |
intersectX | The position of an element vs the viewport. Top = -1, In view = 0, 1 = Bottom |
intersectY | The position of an element vs the viewport. Left = -1, In view = 0, 1 = Right |
viewportX | The horizontal position of an element relative to the center of viewport. Left = -1, centered = 0, and 1 = Right. This is most useful for parallax. |
viewportY | The vertical position of an element relative to the center of viewport. Top = -1, centered = 0, and 1 = Bottom. This is most useful for parallax. |
visible | Equal to 1 if the element is visible in the viewport, 0 if not. Can be tweaked by using the threshold option. |
visibleX | The ratio of visible horizontal content. 0 if invisible, 1 if 100% visible |
visibleY | The ratio of visible vertical content. 0 if invisible, 1 if 100% visible |
Methods
ScrollOut
has a few methods to handle specialized cases. index()
and update()
can be used for manually refreshing the DOM. teardown
is useful when building a Single Page Application.
Method | Description |
---|---|
.index() | Manually searches for elements. This is intended for when DOM elements are removed or inserted by a JS framework. |
.update() | Manually checks if the elements have been updated. This is intended for when a JS framework changes the visual layout of the DOM. |
.teardown() | If you no longer need a ScrollOut instance, call the teardown() function. |
Scrolling Element
Scroll Direction
ScrollOut
detects the direction on the horizontal and vertical axis. This is useful for creating CSS styles that are different when scrolling down vs scrolling up.
Attributes | Description |
---|---|
data-scroll-dir-x | The current horizontal direction -1, 1, or 0 of the scroll. -1 is up, and 1 is down. |
data-scroll-dir-y | The current vertical direction -1, 1, or 0 of the scroll. -1 is left, and 1 is right. |
Variable | Description |
---|---|
--scroll-dir-x | The current horizontal direction -1, 1, or 0 of the scroll. -1 is up, and 1 is down. |
--scroll-dir-y | The current vertical direction -1, 1, or 0 of the scroll. -1 is left, and 1 is right. |
Scroll Percentage
ScrollOut
calculates the total percentage of a scrolling element is scrolled and provides that as a CSS Variable. This is useful for parallax backgrounds or other effects.
Variable | Description |
---|---|
--scroll-percent-x | The ratio of horizontal scroll progress. It starts at 0 and ends at 1. |
--scroll-percent-y | The ratio of vertical scroll progress. It starts at 0 and ends at 1. |
Scroll Targets
Target Dimensions
Variable | Description |
---|---|
--element-width | The current width of the element |
--element-height | The current height of the element |
Target Position
Variable | Description |
---|---|
--intersect-x | The position of an element vs the viewport. Left = -1, In view = 0, 1 = Right |
--intersect-y | The position of an element vs the viewport. Top = -1, In view = 0, 1 = Bottom |
--offset-x | The number of pixels from the left side of the scrolling element. |
--offset-y | The number of pixels from the top of the scrolling element |
--viewport-x | The horizontal position of an element relative to the center of viewport. Left = -1, centered = 0, and 1 = Right. This is most useful for parallax. |
--viewport-y | The vertical position of an element relative to the center of viewport. Top = -1, centered = 0, and 1 = Bottom. This is most useful for parallax. |
Target Visibility
Attribute | Description |
---|---|
data-scroll | "in" or "out". "in" if the element is visible, "out" if it is not. Decorate your elements with this attribute to automatically target these elements. |
Variable | Description |
---|---|
--visible | The value is 1 if the element is considered visible, 0 if not. |
--visible-x | The current ratio of visible content on the horizontal axis (0 to 1) |
--visible-y | The current ratio of visible content on the vertical axis (0 to 1) |
CSS Props Options
For performance / cleanliness reasons, it is desirable to opt into particular CSS Variables. In addition to true/false, the cssProps
options can also accept an object that describes which properties should be enabled or disabled. When specifying this options object, all variables are opt-in. For instance, in the following examples, only --viewport-y
and --visible-y
would be set on the elements:
ScrollOut({
cssProps: {
viewportY: true,
visibleY: true
}
});
Both Target and Scrolling Element CSS Variables are controlled by this option.