viewmotion
v0.1.1 — Stable

Reveal animations
without the bloat.

Your Lighthouse score stays perfect. Your bundle stays under 2 KB. Works with React, Vue, Svelte, Astro, or plain HTML — in 3 lines of code.

Read the docs
$ npm install viewmotion

One observer. Pure CSS. Done.

Viewmotion watches elements entering the viewport with a single global IntersectionObserver and triggers CSS animations. No scroll events. No polling. No runtime cost.

IntersectionObserver

A single global observer monitors all animated elements. When they enter the viewport, a CSS class is applied that triggers the animation. One observer — any number of elements.

CSS @keyframes

Animations are pure CSS keyframes — hardware-accelerated by the browser. No JavaScript animation loop. No requestAnimationFrame. Just the platform doing what it does best.

Zero dependencies

No GSAP. No Framer Motion. No scroll libraries. viewmotion ships under 2 KB gzipped and uses only native browser APIs. Smooth scroll is opt-in via Lenis.

Three lines to animate

Install, initialize, and add data attributes. That’s it.

1

Install

npm install viewmotion
2

Initialize

import "viewmotion/styles.css";
import { initMotion } from "viewmotion";

await initMotion();
3

Animate

<h1 data-motion="fade-up">
  Hello world
</h1>

8 built-in animations

Every preset is a composable CSS keyframe. Scroll to see each one in action. Need a custom animation? Use registerPreset() to add your own.

fade

Pure opacity transition from 0 to 1.

fade-up

Opacity + translate up 24px.

fade-down

Opacity + translate down 24px.

slide-right

Enters from right 32px.

slide-left

Enters from left 32px.

scale-in

Scales up from 92% with fade.

zoom-out

Shrinks from 108% with fade.

blur-in

Fades in with 6px blur dissolve.

Works with your stack

The core library is framework-agnostic. Official adapters bring idiomatic APIs to React, Vue, Svelte, and Astro.

Vanilla / Core

Framework-agnostic. Works with any HTML.

$ npm install viewmotion

React

useMotion hook for refs.

$ npm install viewmotion-react

Vue

v-motion directive + composable.

$ npm install viewmotion-vue

Svelte

use:motion action.

$ npm install viewmotion-svelte

Idiomatic in every framework

Each adapter exposes the API pattern native to its framework. Same animations, zero learning curve.

Vanilla HTML

<script type="module">
  import "viewmotion/styles.css";
  import { initMotion } from "viewmotion";
  await initMotion();
</script>

<h1 data-motion="fade-up">
  Hello world
</h1>

React

import { useMotion } from "viewmotion-react";

function Hero() {
  const ref = useMotion({ preset: "fade-up" });

  return (
    <h1 ref={ref}>Hello</h1>
  );
}

Vue

<script setup>
import { vMotion } from "viewmotion-vue";
</script>

<template>
  <h1 v-motion="{ preset: 'fade-up' }">
    Hello
  </h1>
</template>

Svelte

<script>
  import { motion } from "viewmotion-svelte";
</script>

<h1
  use:motion={{ preset: "fade-up" }}
>
  Hello
</h1>

Cascading reveals, zero effort

Wrap a container with stagger() and each child animates with an automatic incremental delay. Perfect for grids, lists, and cards.

01

Single observer

One IntersectionObserver manages all elements on the page. No per-element setup needed.

02

8 built-in presets

From subtle fades to directional slides. Extend with registerPreset() for custom animations.

03

Reduced motion

Automatically respects prefers-reduced-motion. Elements reveal instantly without animation.

04

Zero runtime deps

No external libraries at runtime. Pure IntersectionObserver + CSS keyframes.

05

SSR-ready

Works with server-rendered HTML, static pages, and any framework's SSR output.

06

Smooth scroll

Optional Lenis integration for buttery smooth scrolling as a peer dependency.

Philosophy

Not a scroll engine.
A reveal system.

viewmotion doesn't try to be GSAP or Framer Motion. It deliberately solves one problem: revealing elements as they enter the viewport with performant, composable CSS animations.

There's no scroll-driven timeline. No spring physics. No animation orchestration. Just battle-tested browser APIs assembled into a clean, minimal package.

The result is a library that ships under 2 KB gzipped, installs in seconds, and delivers the 90% of scroll animations that landing pages actually need.

Performant by default

Animations use CSS transforms & opacity — GPU-composited, never blocking the main thread.

Accessible out of the box

Respects prefers-reduced-motion automatically. No user opt-out required.

Predictable & debuggable

Standard CSS classes & data attributes. Inspect in DevTools like any other element.

Tree-shakeable & extensible

Import only what you use. Add custom presets with registerPreset().

Smaller. Simpler.
No compromises.

viewmotion is built for the 90% of scroll animations landing pages actually need. Not a swiss-army knife — a precision tool.

Feature viewmotion AOS.js Animate.css GSAP ST
Bundle size < 2 KB ~ 14 KB ~ 80 KB ~ 67 KB
Zero dependencies
SSR safe ⚠ Partial ⚠ Partial
Framework adapters Partial
prefers-reduced-motion Automatic Manual Manual Manual
Custom presets API
Stagger support
TypeScript support Partial

Bundle sizes from Bundlephobia. GSAP ST = ScrollTrigger plugin.

Start animating today.

Three lines of code. Zero config. Instant scroll-reveal animations that work with any framework or plain HTML.