@cssints/reveal

Scroll-driven reveal animations for cssints: an element runs one of @cssints/motion's entrance presets as it scrolls into view, on animation-timeline: view() and animation-range, as one chain member of cssints/plugin scope(). In the spirit of the supersonic plugin and lax.js, with the browser doing the work. Where a target lacks scroll-driven animations, a 0.3 kB script plays the same keyframes once when the element enters.

import { cn, hover } from "cssints" with { type: "cssints" };
import { reveal } from "@cssints/reveal" with { type: "cssints" };

export const fade = reveal();
export const card = reveal()
  .preset("slide-in-up")
  .range("entry 0% entry 100%")
  .duration("500ms")
  .easing("linear");
export const tile = cn(reveal().preset("blur-in"), hover(reveal().duration("1s")));
@layer _.k {
  @keyframes kf-7f473efd {
    from {
      opacity: var(--motion-o);
      translate: var(--motion-x) var(--motion-y);
      scale: var(--motion-s);
      filter: blur(var(--motion-b));
    }
  }
  @keyframes kf-4f766ef7 {
    from {
      opacity: var(--motion-o);
    }
  }
  ._reveal-core {
    animation: var(--reveal-k) var(--reveal-d) var(--reveal-e) both;
    animation-range: var(--reveal-g);
    --reveal-k: kf-7f473efd;
    --reveal-rk: kf-4f766ef7;
    --reveal-d: 300ms;
    --reveal-e: ease-out;
    --reveal-g: entry 0% cover 40%;
    --motion-o: 0;
    --motion-x: 0;
    --motion-y: 0;
    --motion-s: 1;
    --motion-b: 0;
    animation-timeline: view();
  }
  @media (prefers-reduced-motion: reduce) {
    ._reveal-core {
      animation-name: var(--reveal-rk);
    }
  }
  /* only when a target lacks scroll-driven animations */
  @supports not (animation-timeline: view()) {
    [data-reveal] ._reveal-core:not([data-reveal-in]) {
      animation-play-state: paused;
    }
  }
}
@layer _.a {
  ._1a9p5a9 {
    --motion-y: 25%;
  }
  ._yorqor {
    --reveal-g: entry 0% entry 100%;
  }
  ._k4abtq {
    --reveal-d: 500ms;
  }
  /* ... */
}

Rules

Browsers

Limits

cd packages/reveal && bun run test            # fixtures through the engine (output by targets, runtime module, conflicts, errors)
cd packages/reveal && bun run test:browsers   # Chrome, Firefox and WebKit through playwright-core

Credits

In the spirit of the supersonic plugin (MIT, Alex Illarionov) and lax.js (MIT, Alex Fox). The presets are @cssints/motion's. No code is copied.