svelte-reveal
v1.1.0
Published
Svelte action that leverages the Intersection Observer API to trigger reveal on scroll transitions
Downloads
3,353
Maintainers
Readme
Svelte Reveal
Svelte Reveal is a library created with the purpose of helping Svelte users add reveal on scroll animations to their web applications in the easiest way possible. This library leverages the Intersection Observer API in order to know when to trigger the animations.
Features
- ⚡️ Near zero config
- 👀 Intersection Observer
- 🧩 Customizable transitions
- 🔌 Extensive API
- 📚 Exhaustive documentation
- 🔥 100% TypeScript
Table of Contents
- Demo
- Usage
- Why Svelte Reveal
- SvelteKit
- Options
- Global config
- API
- Suggestions
- Troubleshooting
- Funding
- Versioning
- Changelog
- License
Demo
You can see Svelte Reveal in action in this StackBlitz project.
Usage
Install the library:
# npm npm install -D svelte-reveal # yarn yarn add -D svelte-reveal # pnpm pnpm add -D svelte-reveal # bun bun add -D svelte-reveal
Import the library in your Svelte component:
<script> import { reveal } from 'svelte-reveal'; </script>
Add the imported
reveal
action to the DOM element you want to transition:<h1 use:reveal>Hello world</h1> <p use:reveal={{ transition: "slide" }}>A paragraph</p>
If you want to use the action on a Svelte component, you need to pass the reveal options via props:
// App.svelte <script> import Heading from './Heading.svelte'; </script> <Heading useReveal={{ transition: "slide" }}>Hello world</Heading>
// Heading.svelte <script lang="ts"> import { reveal, type RevealOptions } from 'svelte-reveal'; export let useReveal: RevealOptions; </script> <h1 use:reveal={ useReveal }> <slot /> </h1>
Using SvelteKit? Please refer to the "SvelteKit" section.
Why Svelte Reveal
If you happened to scout the internet for other similar libraries, you might have noticed that other authors have decided to create their own library using Svelte slots (similar to React children). There is nothing wrong with that approach, but in my opinion it goes a bit against one of Svelte's core purpose: writing more concise code. Having to wrap every to-be-transitioned component adds at least 2 extra lines of code each time, making your files unnecessarily bloated for such a simple add-on.
You might have also noticed people adding event listeners to the window object in order to transition elements, but in terms of performance it doesn't scale very well.
Instead, I decided to use Svelte actions, which are functions you can attach to a DOM element and that allow you to get access to that particular element and hook into its lifecycle. They take up considerably fewer lines of code, and so far I haven't encountered any big obstacle or performance drawback. Morever, this library is backed by the Intersection Observer API, which is great for performance.
SvelteKit
⚠️ This is an active area of research. Please submit a bug report in case of issues.
📅 Last update: April 2024
Since Svelte actions were conceived to operate in a client-side environment, they don't always work 100% in SvelteKit and SSR (server-side rendering) out of the box. Svelte Reveal is no exception, as it needs DOM access, and in order not to incur in weird animation behaviors some small setup is required by the end-users. Out of the following two methods, pick the one that most suit your project requirements.
Without SSR
If your page doesn't need to be server-side rendered then the fix is very trivial. Turn off ssr
in your +page.ts
file as follows.
// +page.ts
export const ssr = false;
With SSR
If your page does need to leverage server-side rendering, the setup remains easy but it requires a few more steps.
Import the bundled stylesheet in your page or layout
// +layout.svelte <script lang="ts"> import "svelte-reveal/styles.css"; ... </script> ...
Add the
sr__hide
css class to every element targeted by Svelte Reveal withuse:reveal
. This will prevent the elements to flicker as soon as the page is hydrated and the DOM is accessible to the library.// +page.svelte <script lang="ts"> import { reveal } from 'svelte-reveal'; </script> <h1 use:reveal class="sr__hide">Hello world</h1>
Options
Depending on the use case, you can either use this library as-is (which applies some default options), or customize it to your liking. If you choose to do so, you can pass an object to this action containing your own options to be applied.
Keep in mind that these options are applied to the single DOM element you add Svelte Reveal to. For global and more in-depth settings, refer to the API section.
| Name | Type | Default | Description |
| ---------- | --------------------------- | ------------------- | ------------------------------------------------------------ |
| disable
| boolean
| false
| When set to false, the transition is disabled for the target element. |
| root
| Element \| Document \| null
| null
| The root element used by the Intersection Observer. |
| rootMargin
| string
| "0px 0px 0px 0px"
| The root margin property of the Intersection Observer. |
| threshold
| number
| 0.6
| The threshold (in percentage from 0.0
to 1.0
) property used by the Intersection Observer to know when its target element is considered visible. |
| preset
| "fade" \| "slide" \| "fly" \| "spin" \| "blur" \| "scale"
| "fade"
| The transition preset that should be applied. Check out the "presets" subsection for more info. |
| reset
| boolean
| false
| When set to true
, the node transitions out when out of view, and is revealed again when back in view.⚠️ Be careful not to overuse this option, as it prevents the Intersection Observer to stop observing the target node. Performance is therefore not guaranteed when many elements have reset
set to true
. |
| duration
| number
| 800
| How long the transition lasts (in ms). |
| delay
| number
| 0
| How long the transition is delayed (in ms) before being triggered. |
| easing
| Easing
| "easeInOutCubic"
| The easing function to use. Check out the full list of available easing functions and this other website to preview timing functions. |
| x
| number
| 0
| The starting offset position in pixels on the x-axis. |
| y
| number
| 0
| The starting offset position in pixels on the y-axis. |
| rotate
| number
| 0
| The starting rotation offset in degrees. |
| opacity
| number
| 0
| The starting opacity value. |
| blur
| number
| 0
| The starting blur value in pixels. |
| scale
| number
| 1
| The starting scale value in percentage. 1
corresponds to 100%
. |
Presets
⚠️ All presets have the
"fade"
preset backed in
Presets are sets of options with predefined values, packaged under a name to achieve a certain transition effect. The following table shows the presets that come bundled with Svelte Reveal and which options they map to.
| Name | Options | Description |
| --------- | ----------------------------- | ------------------------------------------------------------ |
| "fade"
| { opacity: 0 }
| The element fades in gracefully.In practice: opacity: 0 -> 1
|
| "fly"
| { opacity: 0, y: -20 }
| The element fades in and moves along a translation on the y-axis.In practice: opacity: 0 -> 1
+ transform: translateY(-20px -> 0px)
|
| "slide"
| { opacity: 0, x: -20 }
| The element fades in and performs a translation on the x-axis.In practice: opacity: 0 -> 1
+ transform: translateX(-20px -> 0px)
|
| "blur"
| { opacity: 0, blur: 2 }
| The element fades in and becomes unblurred.In practice: opacity: 0 -> 1
+ filter: blur(2px -> 0px)
|
| "scale"
| { opacity: 0, scale: 0.8 }
| The element fades in and gets to the original size.In practice: opacity: 0 -> 1
+ transform: scale(0.8 -> 1)
⚠️ In order to use this transition it is required to use the width
CSS property on the element to reveal. If you are not already using this property for other things, you can set it to width: fit-content
. |
| "spin"
| { opacity: 0, rotate: -10 }
| The element fades in and gets to the original rotation degree.In practice: opacity: 0 -> 1
+ transform: rotate(-10 -> 0)
⚠️ In order to use this transition it is required to use the width
CSS property on the element to reveal. If you are not already using this property for other things, you can use set it to width: fit-content
. |
Callbacks
The following table shows all the callback functions we provide to you.
| Name | Args | Return | Description |
| --------------- | --------------------- | ------ | ------------------------------------------------------------ |
| onRevealStart
| (node: HTMLElement)
| void
| Function that gets fired when the node starts being revealed. |
| onRevealEnd
| (node: HTMLElement)
| void
| Function that gets fired when the node is fully revealed. |
| onResetStart
| (node: HTMLElement)
| void
| Function that gets fired when the reset
option is set to true
and the node starts transitioning out. |
| onResetEnd
| (node: HTMLElement)
| void
| Function that gets fired when the reset
option is set to true
and the node has fully transitioned out. |
| onMount
| (node: HTMLElement)
| void
| Function that gets fired when the node is mounted on the DOM. |
| onUpdate
| (node: HTMLElement)
| void
| Function that gets fired when the action options are updated. |
| onDestroy
| (node: HTMLElement)
| void
| Function that gets fired when the node is unmounted from the DOM. |
Global config
The following table shows how this library is globally configured right of out the box.
| Parameter | (children) | (children) | Type | Default | Description |
| ------------ | ---------- | ------------ | -------------- | ------- | ------------------------------------------------------------ |
| once
| | | boolean
| false
| Whether the reveal effect runs only once (i.e. it doesn't re-run on page reload). |
| responsive
| | | Responsive
| | Specifies how the library handles responsiveness. It can be used to enable/disable the reveal effect on some devices. |
| | mobile
| | DeviceConfig
| | Configuration of mobile devices. |
| | | enabled
| boolean
| true
| Whether the reveal effect is performed on mobile devices. |
| | | breakpoint
| number
| 425
| The max viewport width of mobile devices. |
| | tablet
| | DeviceConfig
| | Configuration of tablet devices. |
| | | enabled
| boolean
| true
| Whether the reveal effect is performed on tablet devices. |
| | | breakpoint
| number
| 768
| The max viewport width of tablet devices. |
| | laptop
| | DeviceConfig
| | Configuration of laptop devices. |
| | | enabled
| boolean
| true
| Whether the reveal effect is performed on laptop devices. |
| | | breakpoint
| number
| 1440
| The max viewport width of laptop devices. |
| | desktop
| | DeviceConfig
| | Configuration of desktop devices. |
| | | enabled
| boolean
| true
| Whether the reveal effect is performed on desktop devices. |
| | | breakpoint
| number
| 2560
| The max viewport width of desktop devices. |
API
⚠️ If you want to customise the behavior of a single DOM node, you are supposed to use options.
Svelte Reveal also exposes several functions you can call to change the default options and global configuration of this library. Since these functions operate on a global level across all components using Svelte Reveal, you are supposed to only call them from a single file, otherwise you'll keep overriding the default options and global config from multiple points.
| Name | Args | Return | Description |
| ----------------------- | ---------------------------------------------- | ---------------------------- | ------------------------------------------------------------ |
| setOnce
| (once: boolean)
| RevealConfig
| Sets the reveal animations activation status on page reload. |
| setDeviceStatus
| (device: Device, status: boolean)
| RevealConfig
| Sets the status of a device. |
| setDevicesStatus
| (devices: Device[], status: boolean)
| RevealConfig
| Sets the status of multiple devices. |
| setDeviceBreakpoint
| (device: Device, breakpoint: number)
| RevealConfig
| Sets the breakpoint of a device. |
| setDevice
| (device: Device, settings: IDevice)
| RevealConfig
| Sets the settings of a device. |
| setResponsive
| (responsive: Responsive)
| RevealConfig
| Updates how responsiveness is handled by the library. |
| setObserverRoot
| (root: Element \| Document \| null)
| IntersectionObserverConfig
| Sets the Intersection Observer root
element. |
| setObserverRootMargin
| (rootMargin: string)
| IntersectionObserverConfig
| Sets the Intersection Observer rootMargin
property. |
| setObserverThreshold
| (threshold: number)
| IntersectionObserverConfig
| Sets the Intersection Observer threshold
property. |
| setObserverConfig
| (observerConfig: IntersectionObserverConfig)
| IntersectionObserverConfig
| Sets the Intersection Observer configuration. |
| setConfig
| (userConfig: RevealConfig)
| RevealConfig
| Updates the library global configuration. |
| setDefaultOptions
| (options: RevealOptions)
| RevealOptions
| Updates the default options to be used for the reveal effect. |
Suggestions
If you need to considerably customize the behavior of this library, I suggest creating a dedicated file and to import it from the top-most component in the components tree of your project. Within that file you can then call the API functions to set global settings or shared transition properties.
// reveal.config.ts
import { setDefaultOptions } from 'svelte-reveal';
setDefaultOptions({
blur: 20,
x: -50,
duration: 3000
});
// App.svelte
<script>
import 'reveal.config';
</script>
<div>{ your markup goes here }</div>
Troubleshooting
Feel free to open a new issue in case of any problems.
Funding
Versioning
This project uses Semantic Versioning to keep track of its version number.