Troubleshooting
When working with layout animations, there are tons of little gotchas and common issues. This lesson is essentially a big list of things you can try, if your layout animation isn't doing what you expect.
- To prevent text from stretching or warping, wrap nested elements in their own Motion component, setting
layout
to"position"
:
<motion.div layout={true}> <motion.p layout="position"> Hello world! </motion.p></motion.div>
- If the text “snaps” to a new position at the start of the transition, it's likely because the characters themselves are shifting around in their DOM rectangle. Use CSS to shrinkwrap the DOM node around the characters:
<div style={{ display: 'flex', justifyContent: 'center', }}> <motion.p> Centered text </motion.p></div>
(I'm using an inline style here so that it all fits in the same snippet. In reality, you should do this in a CSS Module, or however you typically apply CSS.)
- If elements appear to dance or jiggle, make sure that any nested motion components use the same
transition
settings:
<motion.div transition={CUSTOM_SPRING}> <motion.p transition={CUSTOM_SPRING} > Centered text </motion.p></motion.div>
const CUSTOM_SPRING = { type: 'spring', stiffness: 300, damping: 45,}
- If the corners appear to twitch during an animation, make sure you're specifying the
borderRadius
explicitly, usinginitial
:
<motion.div initial={{ borderRadius: 32, }}/>
You can also do the same thing with boxShadow
, though it only works with a single shadow.
- For shared layout animations that seem to teleport around, try wrapping all related elements in a
LayoutGroup
element:
<LayoutGroup> <div> {someCondition && <motion.div layoutId="some-val" />} </div> {!someCondition && <motion.div layoutId="some-val" />}</LayoutGroup>
- If elements appear to blink out of existence during a shared layout animation, make sure you're using the same value for
layoutId
andkey
:
<motion.div layoutId={layoutId}- key={index}+ key={layoutId}/>
- When setting the
layoutId
prop, make sure it's a truthy value (and not0
or''
):
<motion.div layoutId={`${uniqueId}-${index}`}/>
In addition to these gotchas that we've covered, here are some more you might wish to research further, in your own endeavours with Framer Motion:
- If the element doesn't seem to be animating at all, make sure the element isn't set to
display: inline
. If you're animating a<span>
,<a>
, or other inline element, you'll need to setdisplay: block
so that it can be transformed. - If a layout animation is happening when it shouldn't be (eg. when a different part of the DOM changes), you can use layoutRoot to ignore certain changes.
Check out the full Troubleshooting Guide in the Framer Motion docs.
Onwards!
And so, this marks the end of the bonus module on Framer Motion. I hope you've found it helpful. 😄
In these lessons, I chose to go deep into layout animations, since I think it's the killer feature with Framer Motion. It's worth pointing out, though, that Framer Motion has a bunch of other features as well, including support for lots of different gestures, exit animations, and more.
Even within the narrow slice of layout animations, I've shown you the most critical parts of the API, but there's so much more we can do with them! I hope that I've given you a sense of what's possible with this tool, and that you'll continue to experiment and explore. ✨
You can learn more about Framer Motion in the official docs.