motion-solid

Reduce bundle size

motion-solid is tree-shakable: a bundle only contains what it imports. The motion component is the largest import, because it includes every feature. This guide shows the smaller options.

Sizes

Minified and gzipped, without solid-js and @solidjs/web, as measured by the repository's size checks:

ImportSize
motion42.5 kB
m9.6 kB
m + LazyMotion + domAnimation29.4 kB
m + LazyMotion + domMax42.6 kB
animate from @motion-s/solid/dom18.9 kB
scroll from @motion-s/solid/dom3.6 kB
animate from @motion-s/solid/dom/mini3.1 kB

Hooks and other imports add to these numbers, and share code with them.

m and LazyMotion

The m component has the same API as motion, without any features. LazyMotion provides the features to the m components inside it, so only the bundle you pick is included:

import { domAnimation, LazyMotion, m } from "@motion-s/solid"

function App() {
    return (
        <LazyMotion features={domAnimation} strict>
            <m.div animate={{ opacity: 1 }} whileHover={{ scale: 1.05 }} />
        </LazyMotion>
    )
}
  • domMin: animations, variants and exit animations.
  • domAnimation: domMin with hover, tap, focus and in-view gestures.
  • domMax: domAnimation with drag and layout animations.

Use strict to catch motion components that would bring every feature back in.

Loading features later

LazyMotion also takes a function that loads the bundle. With a dynamic import, the features go to their own chunk, which loads after the page has rendered:

// features.ts
import { domAnimation } from "@motion-s/solid"

export default domAnimation
const loadFeatures = () => import("./features").then((res) => res.default)

<LazyMotion features={loadFeatures}>
    <m.div animate={{ opacity: 1 }} />
</LazyMotion>

The initial bundle then only has m and LazyMotion. The m components render with their initial styles, and animate once the features have loaded.

Animating without components

When you only need to animate elements imperatively, skip the components.

animate from @motion-s/solid/dom animates elements, motion values and plain values, with springs and every value type, and without the component code. See animate.

The mini entries animate elements with the browser's Web Animations API, for the smallest size:

  • @motion-s/solid/dom/mini exports animate and animateSequence.
  • @motion-s/solid/mini exports the same, and useAnimate: the useAnimate hook with the mini animate, scoped to a component.
import { useAnimate } from "@motion-s/solid/mini"

function Toast() {
    const [scope, animate] = useAnimate()

    const dismiss = () =>
        animate(scope.current, { opacity: 0, y: -8 }, { duration: 0.2 })

    return (
        <div ref={scope} onClick={dismiss}>
            Saved
        </div>
    )
}

The main entry exports this hook as useAnimateMini.