Lightweight Animation Library for Modern Web – CSS Motion

Lightweight Animation Library for Modern Web – CSS Motion
Lightweight Animation Library for Modern Web – CSS Motion
CSS Motion is a lightweight, framework-agnostic animation library that creates smooth, performant animations triggered by viewport visibility.

It works with vanilla JavaScript, React, Svelte, and other frameworks through a CSS-only animation approach that respects user preferences for reduced motion.

Features:

  • CSS-Only Animations: Animations run entirely in CSS for optimal performance and smooth frame rates.
  • Intersection Observer: Uses native browser APIs for efficient viewport detection without polling.
  • Rich Animation Presets: Ships with a set of pre-configured animations, including fade, slide, scale, blur, and rotation effects.
  • Tree-Shakeable Architecture: Import only the functions you need to minimize bundle size.
  • Composable Configuration: Mix multiple animation effects and timing functions through the merge utility.

See It In Action:

Use Cases:

  • Scroll-triggered content reveals: Animate sections, cards, or text as users scroll down the page.
  • Staggered list animations: Create cascading effects for product grids, feature lists, or timeline elements with built-in stagger utilities.
  • Performance-critical animations: Replace heavy JavaScript animation libraries with lightweight CSS transitions for better frame rates.

How To Use It:

1. Install & import the library into your project.

# NPM
$ npm install css-motion
@import 'css-motion/styles';
import { initObserver, presets, getVarsStyle } from 'css-motion';

2. You can also load the library from a CDN:

import { initObserver, presets, getVarsStyle } from 'https://cdn.jsdelivr.net/npm/css-motion/dist/index.esm.js';

3. Use the getVarsStyle function to generate the necessary CSS custom properties and then add the required classes to your element.

// Initialize once
initObserver();

const element = document.querySelector('.my-element');

// Get animation styles from a preset
const animation = presets.slideUp(0.1, '20px', 0.5); // (delay, distance, duration)
element.style.cssText += getVarsStyle(animation);

// Add classes to enable the animation
element.classList.add('css-motion', 'css-motion--view');

4. For multiple elements with staggered timing:

const items = document.querySelectorAll('.animate-item');
items.forEach((item, index) => {
  const animation = mergeConfigs(
    presets.fadeIn(),
    stagger(index, 0.1)
  );
  item.style.cssText += getVarsStyle(animation);
  item.classList.add('css-motion', 'css-motion--view');
});

5. The React adapter provides both component and hook APIs. Components handle the ref attachment and style application automatically:

import { AnimateOnView, AnimateOnLoad } from 'css-motion/react';
import { presets } from 'css-motion';
function MyComponent() {
  return (
    <>
      <AnimateOnLoad animation={presets.fadeIn()} className="card">
        Animates immediately on mount
      </AnimateOnLoad>
      <AnimateOnView animation={presets.slideUp()} className="card">
        Animates when scrolled into view
      </AnimateOnView>
    </>
  );
}

For cases requiring more control, use the hook API:

import { useAnimateOnView } from 'css-motion/react';
import { presets } from 'css-motion';
function MyComponent() {
  const { ref, style, className } = useAnimateOnView(presets.rotateIn(), {
    threshold: 0.5,
  });
  return (
    <div ref={ref} style={style} className={className}>
      Custom animation with hook API
    </div>
  );
}

6. The Svelte package provides a convenient animate action. You can use animate.onView to trigger the animation when the element enters the viewport or animate.onLoad for an immediate animation.

<script>
  import { animate } from 'css-motion/svelte';
  import { presets } from 'css-motion';
</script>
<!-- Animates when it enters the viewport -->
<div {...animate.onView(presets.fadeIn(), { class: 'card' })}>
  This animates into view.
</div>
<!-- Animates immediately on component load -->
<div {...animate.onLoad(presets.slideUp(), { class: 'card' })}>
  This animates on load.
</div>

7. The library includes 12 preset animations. Each preset accepts optional parameters for customization:

  • fadeIn(delay?, duration?): Simple opacity transition from zero to one.
  • slideUp(delay?, distance?, duration?): Combines fade with vertical translation from bottom.
  • slideDown(delay?, distance?, duration?): Combines fade with vertical translation from top.
  • slideLeft(delay?, distance?, duration?): Combines fade with horizontal translation from left.
  • slideRight(delay?, distance?, duration?): Combines fade with horizontal translation from right.
  • blurUp(delay?, blur?, distance?, duration?): Adds blur filter to vertical slide animation.
  • scaleIn(delay?, scale?, duration?): Combines fade with scale transformation starting below one.
  • scaleOut(delay?, scale?, duration?): Combines fade with scale transformation starting above one.
  • rotateIn(delay?, rotate?, scale?, duration?): Combines fade, rotation, and scale effects.
  • dramatic(delay?, duration?): Complex preset combining blur, slide, scale with custom cubic-bezier timing.
  • bounceIn(delay?, duration?): Scale effect with bounce timing function.
  • zoomIn(delay?, scale?, duration?): Combines scale and blur for zoom effect.
presets.fadeIn(0.1, 0.5);  // 0.1s delay, 0.5s duration
presets.slideUp(0.1, '20px', 0.5);  // Custom distance
presets.scaleIn(0.1, 0.9, 0.5);  // Custom scale factor

8. API methods:

  • initObserver(): Initializes the global Intersection Observer instance. Call once during application startup. Required for vanilla JavaScript implementations but handled automatically in React and Svelte adapters.
  • getVarsStyle(config): Generates a CSS string containing custom property declarations from an animation configuration object. Append this string to element inline styles.
  • mergeConfigs(…configs): Combines multiple animation configuration objects into a single config. Later arguments override earlier ones for conflicting properties.
  • stagger(index, delay): Generates a configuration object with a delay calculated from an index and base delay value. Useful for creating sequential animation effects.

9. Configure animations through the AnimationConfig interface:

Property Type Description
duration number Animation duration in seconds
delay number Animation delay in seconds
timing TimingFunction CSS timing function string
translateX CSSLength Initial X-axis translation
translateY CSSLength Initial Y-axis translation
scale number Initial scale factor
rotate CSSAngle Initial rotation angle
blur CSSLength Initial blur amount
opacityStart number Starting opacity value (0-1)
opacityEnd number Ending opacity value (0-1)
const customAnimation = {
  duration: 0.8,
  delay: 0.2,
  timing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
  translateY: '30px',
  scale: 0.95,
  opacityStart: 0,
};

10. Control viewport detection behavior through IntersectionObserverOptions:

Property Type Description
threshold number Percentage of element visibility required to trigger (0-1)
rootMargin string Margin around viewport for early/late triggering
once boolean Whether animation triggers only once or repeats
<AnimateOnView 
  animation={presets.fadeIn()}
  observerOptions={{ threshold: 0.5, rootMargin: '50px', once: true }}
>
  Content
</AnimateOnView>

11. Animations are controlled through CSS variables that map to configuration properties:

Variable Purpose
–anim-duration Controls animation duration
–anim-delay Controls animation delay
–anim-timing Sets timing function
–anim-translate-x Sets initial X translation
–anim-translate-y Sets initial Y translation
–anim-scale Sets initial scale factor
–anim-rotate Sets initial rotation
–anim-blur Sets initial blur amount
–anim-opacity-start Sets starting opacity
–anim-opacity-end Sets ending opacity

12. The library applies specific classes to elements:

  • .css-motion: Base class containing common animation properties and transition declarations.
  • .css-motion–load: Applied to elements that animate immediately using the @starting-style CSS feature.
  • .css-motion–view: Applied to elements that animate on viewport intersection.
  • .in-view: Automatically added by the Intersection Observer when an element enters the viewport threshold.

Alternatives:

FAQs:

Q: Can I create custom animations beyond the provided presets?
A: Build custom animations by passing configuration objects directly to animation functions. Combine multiple effects using mergeConfigs(). For example, create a custom diagonal slide by merging translateX and translateY properties with a fade effect. The configuration interface accepts any valid CSS values for transforms, timing functions, and other properties.

Q: Why aren’t my animations triggering when elements enter the viewport?
A: Check that you’ve imported the CSS stylesheet and, for vanilla JavaScript, called initObserver(). Verify elements have both the css-motion and css-motion--view classes applied. The element must also have the inline styles from getVarsStyle() applied.

Q: How do I implement animations that repeat each time an element enters the viewport?
A: Set the once option to false in the observer options. The default behavior triggers animations once, but passing { once: false } in the observerOptions parameter makes the Intersection Observer continuously monitor the element. The animation will play each time the element crosses the visibility threshold.

The post Lightweight Animation Library for Modern Web – CSS Motion appeared first on CSS Script.


Discover more from RSS Feeds Cloud

Subscribe to get the latest posts sent to your email.

Discover more from RSS Feeds Cloud

Subscribe now to keep reading and get access to the full archive.

Continue reading