All Projects → maciekgrzybek → svelte-inview

maciekgrzybek / svelte-inview

Licence: other
A Svelte action that monitors an element enters or leaves the viewport.🔥

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to svelte-inview

React Intersection Observer
React implementation of the Intersection Observer API to tell you when an element enters or leaves the viewport.
Stars: ✭ 2,689 (+651.12%)
Mutual labels:  viewport, intersection-observer, intersectionobserver, intersectionobserver-api
svelte-intersection-observer
Detect if an element is in the viewport using the Intersection Observer API
Stars: ✭ 151 (-57.82%)
Mutual labels:  svelte, viewport, intersection-observer, svelte-component
svelte-meteor-data
Reactively track Meteor data inside Svelte components
Stars: ✭ 14 (-96.09%)
Mutual labels:  svelte, svelte3, svelte-js
react-intersection-observer-api-example
Showcasing of the Intersection Observer API in React with createRef()
Stars: ✭ 13 (-96.37%)
Mutual labels:  intersection-observer, intersectionobserver, intersectionobserver-api
svelte-interview-questions
Concepts and Questions related to Svelte - Part of official Svelte resources list
Stars: ✭ 18 (-94.97%)
Mutual labels:  svelte, svelte3, svelte-js
s-date-range-picker
📅 A date range picker built with Svelte
Stars: ✭ 13 (-96.37%)
Mutual labels:  svelte, svelte3, svelte-js
react-intersection-observer-hook
React hook to use IntersectionObserver declaratively
Stars: ✭ 58 (-83.8%)
Mutual labels:  intersection-observer, intersectionobserver
svelte-headlessui
Unofficial Svelte port of Headless UI components
Stars: ✭ 564 (+57.54%)
Mutual labels:  svelte, svelte3
BlazorIntersectionObserver
🔎 Intersection Observer API wrapper for Blazor applications
Stars: ✭ 35 (-90.22%)
Mutual labels:  intersectionobserver, intersectionobserver-api
svelte-form
JSON Schema form for Svelte v3
Stars: ✭ 47 (-86.87%)
Mutual labels:  svelte, svelte3
sveld
Generate TypeScript definitions for your Svelte components
Stars: ✭ 281 (-21.51%)
Mutual labels:  svelte, svelte-component
svelte-spinkit
A collection of loading indicators animated with CSS for Svelte
Stars: ✭ 27 (-92.46%)
Mutual labels:  svelte, svelte3
svelte-typescript-rollup
Svelte + Typescript + Rollup
Stars: ✭ 79 (-77.93%)
Mutual labels:  svelte, svelte-js
svelte-lottie-player
Lottie Player component for Svelte
Stars: ✭ 90 (-74.86%)
Mutual labels:  svelte, svelte-component
memento-svelte-electron-typescript
Template to create a desktop app with Svelte, TailwindCSS, Electron and TypeScript (with electron-updater, electron-reload and electron-builder)
Stars: ✭ 27 (-92.46%)
Mutual labels:  svelte, svelte-js
vue-observable
IntersectionObserver, MutationObserver and PerformanceObserver in Vue.js
Stars: ✭ 24 (-93.3%)
Mutual labels:  viewport, intersection-observer
svelte-webcomponents
A ready-to-use project template to build custom elements (web components) with Svelte 3 with support and examples for web components, jest, sass, nested components with props, eslinting, stylelinting, Github actions, propagating custom events from shadow-DOM to real-DOM etc.
Stars: ✭ 22 (-93.85%)
Mutual labels:  svelte, svelte3
ui-svelte
A component library for Svelte
Stars: ✭ 18 (-94.97%)
Mutual labels:  svelte, svelte3
react-use-observer
Performant react hooks for WebApi Observers, useResizeObserver, useInteractionObserver, useMutationObserver
Stars: ✭ 19 (-94.69%)
Mutual labels:  observer, intersection-observer
mmss-client
No description or website provided.
Stars: ✭ 16 (-95.53%)
Mutual labels:  svelte, svelte3

Svelte Inview

A Svelte action that monitors an element enters or leaves the viewport/parent element. Performant and efficient thanks to using Intersection Observer under the hood. Can be used in multiple projects including lazy loading images, infinite scrolling, playing/pausing the video when in the viewport, tracking user behaviour firing link pre-fetching and animations and many many more.

🔥Check it out live here

Why bother?

  • 👓️ Watch for any element that enters or leaves the viewport (or another wrapper/parent element).
  • 🏎️ Thanks to using Intersection Observer, Svelte Inview is blazing fast and doesn't block the main thread.
  • 📦️ Tiny, yet powerful (just ~2kb). No external dependencies (well, apart from Svelte).
  • 🎛️ Use it in several different scenarios such as lazy loading images, infinite scrolling, playing/pausing the video when in the viewport, firing link pre-fetching, animations and many many more.
  • 🐥 Easy to use API.
  • ↕️ Detects the scrolling direction.

Installation

The only thing you need is Svelte itself.

Svelte Inview is distributed via npm.

$ yarn add svelte-inview
# or
$ npm install --save svelte-inview

⚠️ Modern browsers have the full support of Intersection Observer, but if you need to support ones like IE you can use this simple polyfill. Just install it and import it in your project.

Usage

NOTE: Version 2 was returning observe and unobserve methods on the events. In version 3 they were removed, and the observer and node are being returned instead. So if you used those methods before like this:

event.detail.observe(node);

You'll need to change it to:

event.detail.observer.observe(node);

NOTE: Version 1 was using an Inview component. In version 2 that was changed to action - API is easier to consume, plus the obsolete wrapper is not longer needed. If you still want to use the component, check the documentation for version 1.

Basic Use Case

This is the most basic use case for svelte-inview. Just add the action to the element you want to track - use:inview. You can also pass other configuration props. You can see if the element is visible by checking the inView or from the inside of the callback method - on:change.

<script lang="ts">
  import { inview } from 'svelte-inview';

  let isInView: boolean;
  const options = {};
</script>

  <div
    use:inview={options}
    on:change={(event) => {
      const { inView, entry, scrollDirection, observer, node} = event.detail;
      isInView = inView;
    }}
    on:enter={(event) => {
      const { inView, entry, scrollDirection, observer, node} = event.detail;
      isInView = inView;
    }}
    on:leave={(event) => {
      const { inView, entry, scrollDirection, observer, node} = event.detail;
      isInView = inView;
    }}
    on:init={(event) => {
      const { observer, node } = event.detail;
    }}>{isInView ? 'Hey I am in the viewport' : 'Bye, Bye'}</div>

Lazy Loading Images

Svelte Inview lets you easily lazy load images. For a better UX we can pass a rootMargin="50px" props, so the image will be loaded when scroll is 50px before the viewport. After it appears in the viewport, you don't want to observe it anymore, hence the unobserveOnEnter props set to true.

<script lang="ts">
  import { inview } from 'svelte-inview';
  import type { ObserverEventDetails, Options } from 'svelte-inview';

  let isInView;
  const options: Options = {
    rootMargin: '50px',
    unobserveOnEnter: true,
  };

  const handleChange = ({ detail }: CustomEvent<ObserverEventDetails>) => (isInView = detail.inView);
</script>

<div use:inview="{options}" on:change="{handleChange}">
  {#if isInView}
  <img src="path/to/image.jpg" />
  {:else}
  <div class="placeholder" />
  {/if}
</div>

Video Control

You can play/pause a video when it's in/out of the viewport. Simply pass correct methods in on:enter and on:leave callbacks.

<script lang="ts">
  import { inview } from 'svelte-inview';
  import type { ObserverEventDetails } from 'svelte-inview';

  let isInView: boolean;
  let videoRef: HTMLElement;
</script>

  <div
    use:inview
    on:enter={() => videoRef.play()}
    on:leave={() => videoRef.pause()}
  >
    <video width="500" controls bind:this={videoRef}>
      <source src="path/to/video.mp4" type="video/mp4" />
    </video>
  </div>

Animations

You can also add some cool animations when an element enters the viewport. To make sure the animation won't fire too soon you can pass a negative value to rootMargin. When inView is true, add an animation class to your target. Additionally, you can detect the scroll direction to make the animations even cooler!

<script lang="ts">
  import { inview } from 'svelte-inview';
  import type { ObserverEventDetails, ScrollDirection, Options } from 'svelte-inview';

  let isInView: boolean;
  let scrollDirection: ScrollDirection;
  const options: Options = {
    rootMargin: '-50px',
    unobserveOnEnter: true,
  };

  const handleChange = ({ detail }: CustomEvent<ObserverEventDetails>) => {
    isInView = detail.inView;
    scrollDirection = detail.scrollDirection.vertical;
  };
</script>

  <div use:inview={options} on:change={handleChange}>
    <div
      class:animate={isInView}
      class:animateFromBottom={scrollDirection === 'down'}
      class:animateFromTop={scrollDirection === 'top'}>
      Animate me!
    </div>
  </div>

API

Props

Name Type Default Description Required
options.root HTMLElement window The element that is used as the viewport for checking visibility of the target. Must be the ancestor of the target. false
options.rootMargin string 0px Margin around the root element. Values similar to the CSS margin property, e.g. "10px 20px 30px 40px". Can also be a percentage. See more. false
options.threshold number or number[] 0 Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed. If you only want to detect when visibility passes the 50% mark, you can use a value of 0.5. If you want the callback to run every time visibility passes another 25%, you would specify the array [0, 0.25, 0.5, 0.75, 1]. The default is 0 (meaning as soon as even one pixel is visible, the callback will be run) false
options.unobserveOnEnter boolean false If true, target element stops being observed after the first time it appears in the viewport. Can be used when you want to fire the callback only once. false
on:change function - Event fired every time the target element meets the specified threshold. Receives event object as an argument. Inside of event.detail you can find all the arguments specified here. false
on:enter function - Event fired every time the target element enters the viewport. Receives event object as an argument. Inside of event.detail you can find all the arguments specified here . false
on:leave function - Event fired every time the target element leaves the viewport. Receives event object as an argument. Inside of event.detail you can find all the arguments specified here . false
on:init function - Event fired on action initialization, before the observer starts observing the element. Receives lifecycle argumetns specified here false

Observer events arguments

Name Type Description
inView boolean Visibility state of the target element. If it's true, target passed at least the value of the threshold props.
entry IntersectionObserverEntry Intersection Observer entry object generated every time when IO callback is fired.
scrollDirection.vertical up or down Vertical scrolling direction.
scrollDirection.horizontal left or right Horizontal scrolling direction.
node HTMLElement Element that is being observed
observer IntersectionObserver Intersection Observer instance for the observed element. Among others, it allows to "turn off" the observer at the very beginning.

Lifecycle events arguments

Name Type Description
node HTMLElement Element that is being observed
observer IntersectionObserver Intersection Observer instance for the observed element. Among others, it allows to "turn off" the observer at the very beginning.

Additional Info

Usage with rootMargin

If you want to increase or decrease the area of the root, just pass the rootMargin. On the image below you can see the blue area being the root. It means that every time, the target element will enter or leave that area (or meet the specified threshold), a callback will be fired.

Usage of rootMargin

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Maciek Grzybek - @grzybek_maciek - [email protected] - www.maciekgrzybek.dev

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].