Version v2.0.1 Size 2.0 KB gzip Dependencies Zero dependencies
Why Necromancer?
Native Web Animations API calls do not provide lifecycle ownership, reduced-motion policy, grouped playback, or layout transitions. Necromancer retains native keyframes and timing options while making ownership explicit for a component or DOM feature. Its default 180ms duration makes the smallest call visible without hiding native timing control.
// Before
const animation = element.animate(keyframes, { duration: 180 });
animation.addEventListener('cancel', removeListeners);
// After
const animation = animate(element, keyframes, { duration: 180 });
animation.dispose();| Feature | Native WAAPI | Necromancer | Motion One |
|---|---|---|---|
| Bundle size | 0 B | 2.0 KB | ~18 kB |
| Root dependencies | |||
| Lifecycle handle | Manual | dispose() | Library-specific controls |
| Reduced motion | Manual | motion: 'system' default | Configuration required |
| Layout transitions | Manual FLIP math | captureLayout().animate() | Separate API |
Use Necromancer when you need native browser animations with explicit cancellation, reduced-motion behavior, staggered groups, or positional FLIP transitions.
Consider CSS transitions when a static style change needs no playback control, cleanup, or layout measurement.
Installation
pnpm add @vielzeug/necromancernpm install @vielzeug/necromanceryarn add @vielzeug/necromancerQuick Start
Start the animation after its DOM element mounts and release it when its UI owner is removed.
import { animate } from '@vielzeug/necromancer';
const notice = document.createElement('p');
notice.textContent = 'Saved';
document.body.append(notice);
const animation = animate(
notice,
[{ opacity: 0, transform: 'translateY(8px)' }, { opacity: 1, transform: 'translateY(0)' }],
{ duration: 180, easing: 'ease-out' },
);
await animation.result;
animation.dispose();Features
animate()— Native element animation with lifecycle ownership and direct native accessanimateEach()— Group ownership with stable keyframe factories andstaggercaptureLayout()— One-shot FLIP transition with additivetranslate(position) andscale(size)motion—'system'reduced-motion support with explicit reduced outcomesinterrupt: 'cancel'— Replace active Necromancer-owned animation on an elementsignal— Abort a handle from its parent lifecycledispose()— Idempotent cleanup with[Symbol.dispose]()
Deliberate Scope
Necromancer owns explicit WAAPI keyframes. It does not generate CSS keyframes, observe CSS transitions, watch mutations, simulate springs, interpolate SVG paths, or run a JavaScript tween loop. Use CSS for declarative style changes and choose a dedicated tool when those capabilities are required.