DEV Community

Cover image for Solid + GSAP: The superhero we need
Henrique Ramos
Henrique Ramos

Posted on

Solid + GSAP: The superhero we need

Have you ever created a page and felt like it lacks the SAUCE? In my opinion, that drip usually comes from micro-interactions (small interactions with the sole purpose of delighting users). There are many libraries around for creating them, but my favorite one is GSAP, which allows creating performant and complex animations easily.

When using GSAP with React, however, the integration doesn't feel right: creating a Tween/Timeline and storing it in a React.useRef(), adding .to()'s and .from()'s inside a React.useEffect() looks strange to me. This is needed in order to prevent re-declaring on every render, which would re-trigger animations every time something changes in the DOM tree.

This is where SolidJS is brought into play. It looks like React, but has a main difference. according to its documentation:

Every Component executes once and it is the Hooks and bindings that execute many times as their dependencies update.

This means no useRef needed for storing a timeline. In Solid you may simply declare it like this:

const tl = gsap.timeline({paused: true});
Enter fullscreen mode Exit fullscreen mode

And it won't be re-declared on every render. Very cool, eh? This approach is useful for most libraries thatinteract with the DOM to add transitions and animations (ScrollReveal.js, for example).

Animating with GSAP in Solid.js

When adding an animation to a timeline, GSAP needs to know which element should be animated. This can be done using an element reference. There are two ways of getting a ref in Solid:

  1. Pass a ref variable to a JSX element and add the animation inside onMount:
  let containerRef;
  onMount(() => {
    gsap.to(containerRef, {
      // TODO: animation
    });
  });
  return <div ref={containerRef} />;
Enter fullscreen mode Exit fullscreen mode
  1. Or, my favorite one, using custom directives:
const animation = (element) => {
  // code goes here
};

return <div use:animation />;
Enter fullscreen mode Exit fullscreen mode

Custom directives are syntax sugar over ref, which allows us to easily attach multiple directives to a single element. A directive is a function that receives an Element and an Accessor as arguments, that looks like this:

const hoverAnimation = (el, _accessor) => {
  const animation = gsap.to(el, {
    // properties
  });

  el.addEventListener("mouseenter", () => {
    animation.play();
  });

  el.addEventListener("mouseleave", () => {
    animation.pause();
  });
};
Enter fullscreen mode Exit fullscreen mode

And may then be added to any element like this:

const App () => (
  <div use:hoverAnimation />
  <div use:hoverAnimation />
);
Enter fullscreen mode Exit fullscreen mode

An element can have multiple directives, and a directive can be used in multiple elements, making it possible to create GSAP animations that can be re-used throughout your app.

Check out this live demo of an object that changes it background color on hover:

Discussion (3)

Collapse
aquaductape profile image
Caleb Taylor

Nice modification of the gsap character to have solid theme, did you design it?

Collapse
hnrq profile image
Henrique Ramos Author • Edited on

Thanks!! Yea, I made it in Illustrator, haha

Collapse
stevemk42 profile image
Steve

Nice one.. the directives use, I mean. Clever and simple. Thanx ! Its definitely all about that drip of sauce lol