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.
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";
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.
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.
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.
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.
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!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!