Morphing UI Transitions with React Morph

joshtronic

Love them or hate them, animations in modern web design are probably here to stay. Unlike the glory days of jQuery, React out of the box does not provide any mechanism to perform such animations. Sure you could do a small bit of CSS wizardry to animate elements, but what if want to morph one set of elements into another? What’s were react-morph comes into play.

react-morph is a small JavaScript library that provides a <ReactMorph> component that leverages render props to easily create morphing effects in your React app.

Getting Started

Before we can get started, we need to add react-morph to our project with either npm or yarn:

# via npm
$ npm install --save react-morph

# via yarn
$ yarn add react-morph

Be sure to include react-morph in your project wherever you’d like to use it:

import ReactMorph from "react-morph";

Gotchas

Before we dive deeper into react-morph, I want to talk a bit about the caveats or “gotchas” with this library.

First, like most open source offerings, it is a work in progress. A lot of things are works in progress though. Heck, even React is ;)

Next, react-morph is quite sensitive to whitespace as it can introduce additional spacing to an element and throw off the morphing animation. You may need to set your element to display: inline-block or wrap all of the content in another element.

As mentioned, additional spacing can cause problems so things like margins can also give you grief. Be sure to match the margins on both elements in your transition or simply wrap things up with another element.

List items introduce similar issues and applying list-style: none should help things along.

If things are still acting weird, you may need to add in some placeholder elements to avoid additional distortion.

Animations in general can be tricky to get just right so I don’t think any of these little quirks should sway you from this library.

Usage

The usage of react-morph is pretty simple.

Using <ReactMorph> exposes a series of properties that we can use to flag our different transition states (from and to), animation tweens (fadeIn and fadeOut) and a function that you can fire to start the transition (go).

The from and to properties take a string property that will serve as the key to link the states together for transitioning.

Basic Morphing

The most basic example I could think of is taking some text and morphing it into some other text.

<ReactMorph>
  {({ from, to, fadeIn, fadeOut, go }) => (
    <div>
      <a onClick={() => go(1)}>
        <h3 {...from("text")} style={{ display: "inline-block" }}>
          See ya later, alligator...
        </h3>
        <p {...fadeOut()}>Click the text above ;)</p>
      </a>
      <div>
        <h3 {...to("text")} style={{ display: "inline-block" }}>
          After awhile, crocodile!
        </h3>
        <div>
          <a onClick={() => go(0)} {...fadeIn()}>
            Would you like to redo?
          </a>
        </div>
      </div>
    </div>
  )}
</ReactMorph>

Nothing too crazy here. We simply wrap both of our states in <ReactMorph>, setup our click events to use go() to go between states and to(key) to identify the parts of the state.

As you can see, some of the elements have been styled to display inline-block. This removed some weird quirks with the elements popping around on the page a bit.

It’s also worth noting that react-morph appears to only handle two states. Since go() accepts an integer, I thought I’d try to set things up with a third state and well, no dice.

More Complex Usage

Morphing text is great to showcase what react-morph can do, but it’s probably not how you’d use this library in your app.

A bit more of a real world example would taking a button that a user clicks on to reveal a menu and morphing said button into a menu:

<ReactMorph>
  {({ from, to, go }) => (
    <div
      style={{
        display: "flex",
        justifyContent: "center",
        position: "relative",
      }}
    >
      <button
        onClick={() => go(1)}
        {...from("menu")}
        style={{ position: "absolute" }}
      >
        Click to Open
      </button>
      <div
        style={{
          backgroundColor: "#6DB65B",
          border: "2px solid #008f68",
          padding: 10,
          position: "absolute",
        }}
        {...to("menu")}
      >
        <div
          style={{
            alignItems: "center",
            display: "flex",
            justifyContent: "space-between",
            width: "100%",
          }}
        >
          <strong>Menu</strong>
          <button onClick={() => go(0)}>X</button>
        </div>
        <hr />
        <div>Menu Item 1</div>
        <div>Menu Item 2</div>
        <div>Menu Item 3</div>
      </div>
    </div>
  )}
</ReactMorph>

Same concepts as before, just a bit of a different approach to the styling to get each state to seemingly occupy the same position.

Conclusion

Caveats aside, react-morph makes it very easy to drop in some more sophisticated morphing animations between elements in your React app.

I hope you enjoyed this post and if you’re interested in seeing a demo of the code from this post, you can check it out over on CodeSandbox.

Enjoy! 💥

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#