Skip to content

InView

Framework-agnostic engines for scroll, element visibility, and viewport-relative position — with adapters for Vue 3, Nuxt, and React sharing one requestAnimationFrame loop and a pooled IntersectionObserver.

Features

  • Scroll tracking — position, direction, progress, and velocity for the window or a scrollable element, all derived on one shared rAF loop instead of a separate loop per subscriber.
  • Visibility tracking — reactive IntersectionObserver-backed visibility with enter/leave edge detection and a once mode. Observers are pooled by (root, rootMargin, threshold), so many elements with the same options share one native observer.
  • Element viewport position — an element's bounding rect, how far it's traveled through the viewport (viewportProgress, 0..1), and its distance from the viewport's center — the geometry a reveal effect or progress indicator actually needs, already computed.
  • A parallax layer primitive — turns viewportProgress into a CSS transform with a configurable speed, axis, edge clamping, and easing, and disables itself under prefers-reduced-motion automatically.
  • SSR-safe everywhere — every engine and composable/hook returns a static no-op snapshot when there's no window, and starts a real subscription once it's running on the client — no <ClientOnly> wrapping required.
  • Vue, Nuxt, and React adapters over one coreuseScroll, useElementVisibility, useElementViewport, and useParallaxLayer exist as Vue composables, auto-imported Nuxt composables, and React hooks with the same API and behavior — all three built on the same framework-agnostic engines underneath.

How It Works

The package is four npm packages sharing one architecture: a framework-agnostic core (@macrulez/inview-core) does the actual work — scroll tracking, IntersectionObserver pooling, rAF batching — with no framework dependency at all. @macrulez/inview-vue wraps each core engine in a reactive composable (Refs in, Refs out). @macrulez/inview-react wraps the same core engines in hooks built on useSyncExternalStore, mirroring the Vue composables' API 1:1 but with plain values instead of refs. @macrulez/inview-nuxt is a thin Nuxt module on top of the Vue package: it auto-imports every composable/utility and seeds their SSR-safe defaults from nuxt.config.ts on the client.

Picking an adapter is the only decision — install @macrulez/inview-vue for Vue (or let @macrulez/inview-nuxt pull it in), or @macrulez/inview-react for React. The underlying engines, and the options/behavior they expose, stay the same either way.