DEV Community

Fazal Shah
Fazal Shah

Posted on

Lottie Animations in Solid.js: A Complete Guide

SolidJS's fine-grained reactivity pairs well with Lottie's programmatic control API. Here's how to integrate them cleanly.


Setup

npm create solid@latest my-app
cd my-app
npm install @lottiefiles/dotlottie-web
Enter fullscreen mode Exit fullscreen mode

Basic Component

import { onMount, onCleanup } from 'solid-js';
import { DotLottie } from '@lottiefiles/dotlottie-web';

function LottiePlayer({ src, loop = true, autoplay = true }) {
  let canvasRef;
  let dotLottie;

  onMount(() => {
    dotLottie = new DotLottie({
      canvas: canvasRef,
      src,
      loop,
      autoplay,
    });
  });

  onCleanup(() => {
    dotLottie?.destroy();
  });

  return <canvas ref={canvasRef} width="200" height="200" />;
}

export default LottiePlayer;
Enter fullscreen mode Exit fullscreen mode

onMount and onCleanup replace React's useEffect with cleanup return. In SolidJS, refs are assigned directly — no useRef.


Reactive Controls

SolidJS signals integrate naturally with Lottie's playback API:

import { createSignal, onMount, onCleanup } from 'solid-js';
import { DotLottie } from '@lottiefiles/dotlottie-web';

function InteractiveLottie({ src }) {
  let canvasRef;
  let dotLottie;
  const [playing, setPlaying] = createSignal(true);
  const [speed, setSpeed] = createSignal(1);

  onMount(() => {
    dotLottie = new DotLottie({
      canvas: canvasRef,
      src,
      loop: true,
      autoplay: true,
    });
  });

  const togglePlay = () => {
    if (playing()) {
      dotLottie.pause();
    } else {
      dotLottie.play();
    }
    setPlaying(p => !p);
  };

  const changeSpeed = (newSpeed) => {
    dotLottie.setSpeed(newSpeed);
    setSpeed(newSpeed);
  };

  onCleanup(() => dotLottie?.destroy());

  return (
    <div>
      <canvas ref={canvasRef} width="200" height="200" />
      <button onClick={togglePlay}>{playing() ? 'Pause' : 'Play'}</button>
      <input
        type="range"
        min="0.5"
        max="3"
        step="0.5"
        value={speed()}
        onInput={(e) => changeSpeed(Number(e.target.value))}
      />
      <span>{speed()}x</span>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Using lottie-web (SVG Renderer)

If you prefer SVG rendering or need addValueCallback for color changes:

npm install lottie-web
Enter fullscreen mode Exit fullscreen mode
import lottie from 'lottie-web';
import { onMount, onCleanup } from 'solid-js';

function LottieSVG({ path }) {
  let containerRef;
  let anim;

  onMount(() => {
    anim = lottie.loadAnimation({
      container: containerRef,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      path,
    });
  });

  onCleanup(() => anim?.destroy());

  return <div ref={containerRef} style={{ width: '200px', height: '200px' }} />;
}
Enter fullscreen mode Exit fullscreen mode

Lazy Loading

For animations below the fold, use an Intersection Observer:

import { createSignal, onMount, onCleanup } from 'solid-js';
import { DotLottie } from '@lottiefiles/dotlottie-web';

function LazyLottie({ src }) {
  let canvasRef;
  let wrapperRef;
  let dotLottie;
  const [loaded, setLoaded] = createSignal(false);

  onMount(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && !loaded()) {
          setLoaded(true);
          dotLottie = new DotLottie({
            canvas: canvasRef,
            src,
            loop: true,
            autoplay: true,
          });
          observer.disconnect();
        }
      },
      { threshold: 0.1 }
    );
    observer.observe(wrapperRef);
    onCleanup(() => observer.disconnect());
  });

  onCleanup(() => dotLottie?.destroy());

  return (
    <div ref={wrapperRef} style={{ width: '200px', height: '200px' }}>
      {loaded() && <canvas ref={canvasRef} width="200" height="200" />}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Preparing Animation Files

Before integrating:

  1. Preview at IconKing — check colors and bounds
  2. Edit colors directly in the browser — no After Effects needed
  3. Convert .json → .lottie at IconKing — saves ~75% file size

The .lottie format is the right choice for SolidJS projects targeting performance metrics.


Summary

Pattern SolidJS API Notes
Mount animation onMount Runs after DOM is ready
Cleanup onCleanup Destroy to prevent memory leaks
Refs let ref; <div ref={ref} Direct assignment, no useRef
Reactive state createSignal Connect to Lottie playback API

Top comments (0)