Comparison with other React FLIP libraries
|Animate parent's size without warping children||❌||❌||✅|
|Use real FLIP instead of cloning & crossfading||✅||❌||✅|
|Use springs for animations||❌||❌||✅|
|Support spring-based stagger effects||❌||❌||✅|
|Usable with frameworks other than React||❌||❌||✅|
npm install react-flip-toolkit or
yarn add react-flip-toolkit
Wrap all animated children with a single
Flippercomponent that has a
flipKeyprop that changes every time animations should happen.
Wrap elements that should be animated with
Flippedcomponents that have a
flipIdprop matching them across renders.
Table of Contents
- Forkable Examples
- The Components
- Library details
Simple Example: An Expanding Div
import React useState from 'react'import Flipper Flipped from 'react-flip-toolkit'const AnimatedSquare =const fullScreen setFullScreen =const toggleFullScreen =return<Flipper =><Flipped ="square"><div==/></Flipped></Flipper>
Simple Example: Two Divs
import React useState from 'react'import Flipper Flipped from 'react-flip-toolkit'const Square = toggleFullScreen<Flipped ="square"><div ="square" = /></Flipped>const FullScreenSquare = toggleFullScreen<Flipped ="square"><div ="full-screen-square" = /></Flipped>const AnimatedSquare =const fullScreen setFullScreen =const toggleFullScreen =return<Flipper =>fullScreen ?<FullScreenSquare = />:<Square = /></Flipper>
Simple Example: List Shuffle
import React useState from 'react'import Flipper Flipped from 'react-flip-toolkit'import shuffle from 'lodash.shuffle'const ListShuffler =const data setData =const shuffleList =return<Flipper =><button => shuffle</button><ul ="list">data</ul></Flipper>
Add some interest to a dynamic list of cards by animating changes to cards' sizes and positions.
react-flip-toolkit library offers spring-driven stagger configurations so that you can achieve complex sequenced effects.
For the most basic stagger effect, you can simply add a
stagger boolean prop to your
<Flipped = ><AnimatedListItem/></Flipped>
react-flip-toolkit uses springs for animations. To customize the spring, you can pass in a preset name:
// spring preset can be one of: "stiff", "noWobble", "gentle", "veryGentle", or "wobbly"<Flipper ='foo' ='wobbly'>/* Flipped components go here...*/</Flipper>
or a custom spring config:
<Flipper ='foo' = >/* Flipped components go here...*/</Flipper>
Nested Scale Transforms
Interesting animations often involve scale transforms in addition to simple translate transforms. The problem with scale animations has to do with children — if you scale a div up 2x, you will warp any children it has by scaling them up too, creating a weird-looking animation. That's why this library allows you to wrap the child with a
Flipped component that has an
inverseFlipId to counteract the transforms of the parent:
<Flipped =><div><Flipped = ><div>some text that will not be warped</div></Flipped></div></Flipped>
By default, both the scale and the translation transforms of the parent will be counteracted (this allows children components to make their own FLIP animations without being affected by the parent).
But for many use cases, you'll want to additionally specify the
scale prop to limit the adjustment to the scale and allow the positioning to move with the parent.
Note: the DOM element with the inverse transform should lie flush against its parent container for the most seamless animation.
That means any layout styles — padding, flexbox, etc—should be applied to the inverted container (the element wrapped with a
Flipped component with an
inverseFlipId) rather than the parent
Route-based Animations With React Router
react-flip-toolkit works great with client-side routers to provide route-driven transitions:
The parent wrapper component that contains all the elements to be animated. You'll often need only one of these per page, but sometimes it will be more convenient to have multiple
Flipper regions of your page concerned with different transitions.
<Flipper =>/* children */</Flipper>
||Changing this tells
||One or more element children|
||Provide a string referencing one of the spring presets —
||Whether or not
||If you'd like the wrapper element created by the
||A class applied to the wrapper element, helpful for styling.|
||Provide configuration for staggered
staggerConfig=// the "default" config will apply to staggered elements without explicit keysdefault:// default direction is forwardsreverse: true// default is .1, 0 < n < 1speed: 5// this will apply to Flipped elements with the prop stagger='namedStagger'namedStagger : speed: 2
||Sometimes, you'll want the animated children of
||This experimental prop will pause your animation right at the initial application of FLIP-ped styles. That will allow you to inspect the state of the animation at the very beginning, when it should look similar or identical to the UI before the animation began.|
||In general, the
||This callback prop will be called when all individual FLIP animations have completed. Its single argument is a list of
Wraps an element that should be animated.
E.g. in one component you can have
<Flipped ="coolDiv"><div ="small" /></Flipped>
and in another component somewhere else you can have
<Flipped ="coolDiv"><div ="big" /></Flipped>
and they will be tweened by
Flipped component produces no markup, it simply passes some props down to its wrapped child.
Wrapping a React Component
If you want to wrap a React component rather than a JSX element like a
div, you can provide a render prop and then apply the
flippedProps directly to the wrapped element in your component:
<Flipped><MyCoolComponent = /></Flipped>const MyCoolComponent = flippedProps <div />
You can also simply provide a regular React component as long as that component spreads unrecognized props directly onto the wrapped element (this technique works well for wrapping styled components):
<Flipped><MyCoolComponent /></Flipped>const MyCoolComponent = knownProp ...rest <div />
||Wrap a single element, React component, or render prop child with the
|flipId (required unless inverseFlipId is provided)||-||
||Use this to tell
||Refer to the id of the parent
||This is a convenience method to apply the proper CSS
||Provide a string referencing one of the spring presets —
||Provide a natural, spring-based staggering effect in which the spring easing of each item is pinned to the previous one's movement. Provide
||Delay an animation by providing a reference to another
The above animation uses
onExit callbacks for fade-in and fade-out animations.
||Called when the element first appears in the DOM. It is provided a reference to the DOM element being transitioned as the first argument, and the index of the element relative to all appearing elements as the second. Note: If you provide an
||Called when the FLIP animation for the element starts. It is provided a reference to the DOM element being transitioned as the first argument.|
||Called with the current spring value (normally between 0 - 1 but might briefly go over or under that range depending on the level of "bounciness" of the spring). Useful if you'd like to tween other, non-FLIP animations in concert with a FLIP transition.|
||Called when the FLIP animation completes. It is provided a reference to the DOM element being transitioned as the first argument. (If transitions are interruped by new ones,
||Called when the element is removed from the DOM. It must call the
By default the FLIP-ped elements' translate, scale, and opacity properties are all transformed. However, certain effects require more control so if you specify any of these props, only the specified attribute(s) will be tweened:
Functions to control when FLIP happens
||A function provided with the current and previous
||A function provided with the current and previous
As a convenience,
react-flip-toolkit exports a tiny function to access the same spring system used to create FLIP transitions.
import spring from 'react-flip-toolkit';
- Tested in latest Chrome, Firefox, Safari, Edge, and IE 11 with Browserstack.
- For IE11 compatability, make sure you're polyfilling the
- Requires React 16+
- Uses Rematrix for matrix calculations and a simplified fork of Rebound for spring animations
Problem #1: Nothing is happening
- Make sure you're updating the
flipKeyattribute in the
Flippercomponent whenever an animation should happen.
- If one of your
Flippedcomponents is wrapping another React component rather than a DOM element, use a render prop to get the Flipped props and pass down to the necessary DOM element.
- Is the element that's receiving props from
Flippedvisible in the DOM?
react-flip-toolkitattempts to optimize performance by not animating elements that are off-screen or elements that have no width or height.
display:inlineelements cannot be animated. If you want an
inlineelement to animate, set
Problem #2: Things look weird / animations aren't behaving
- Check to make sure all
flipIds are unique. At any point, there can only be one element with a specified
flipIdon the page. If there are multiple
Flippedelements on the page with the same id, the animation will break.
- Make sure you are animating the element you want to animate and not, for instance, a wrapper div. If you are animating an inline element like some text, but have wrapped it in a
div, you're actually animating the div, which might have a much wider width that you'd expect at certain points, which will throw off the animation. Check to see if you need to add an
inline-blockstyle to the animated element.
- Make sure you don't have any competing CSS transitions on the element in question.
- If you are animating an image, try giving the image hard-coded dimensions and seeing if that fixes the problem. (If you are relying on the innate dimensions of the image, it might not have been fully rendered by the browser in time for the new image dimensions to be measured.)
Problem #3: It's still not working
- Try out the
debugprop. If you still can't figure out what's going wrong, you can add the the
debugprop directly on your
Flippercomponent to pause transitions at the beginning.
- If you think something might actually be broken, or are completely stuck, feel free to make an issue.
React-flip-toolkit does a lot of work under the hood to try to maximize the performance of your animations — for instance, off-screen elements won't be animated, and style updates are batched to prevent layout thrashing.
However, if you are building particularly complex animations—ones that involve dozens of elements or large images— there are some additional strategies you can use to ensure performant animations.
When you trigger a complex FLIP animation with
React could be spending vital milliseconds doing unnecessary reconciliation work before allowing the animation to start. If you notice a slight delay between when the animation is triggered, and when it begins, this is probably the culprit. To short-circuit this possibly unnecessary work, try memoizing your component by using
PureComponent for your animated elements, and seeing if you can refactor your code to minimize prop updates to animated children when an animation is about to occur.
This CSS property tells the browser to anticipate changes to an element. It should be used with caution, because it can increase browser resource usage. If you notice rendering issues in your animation, I would recommend trying it out and seeing if it increases the performance of the animation.