react-flip-toolkit
A lightweight magic-move library for configurable layout transitions
Top Related Projects
Open source, production-ready animation and gesture library for React
An easy way to perform animations when a React component enters or leaves the DOM
A spring that solves your animation problems.
✌️ A spring physics based React animation library
🇨🇭 A React renderer for Three.js
🎊 A collection of animations for inline style libraries
Quick Overview
React Flip Toolkit is a lightweight library for creating highly performant animations and transitions in React applications. It provides a simple API for implementing FLIP (First, Last, Invert, Play) animations, which are particularly useful for smooth list reordering and shared element transitions.
Pros
- Easy to use with a simple, declarative API
- Highly performant animations using FLIP technique
- Flexible and customizable for various animation scenarios
- Works well with existing React components and libraries
Cons
- Limited documentation and examples for advanced use cases
- May require additional setup for complex animations
- Learning curve for developers unfamiliar with FLIP animations
- Potential performance issues with a large number of animated elements
Code Examples
- Basic FLIP animation:
import { Flipper, Flipped } from 'react-flip-toolkit'
function MyComponent({ items }) {
return (
<Flipper flipKey={items.join('')}>
{items.map(item => (
<Flipped key={item} flipId={item}>
<div>{item}</div>
</Flipped>
))}
</Flipper>
)
}
- Shared element transition:
import { Flipper, Flipped } from 'react-flip-toolkit'
function App() {
const [isExpanded, setIsExpanded] = useState(false)
return (
<Flipper flipKey={isExpanded}>
<Flipped flipId="box">
<div onClick={() => setIsExpanded(!isExpanded)}>
{isExpanded ? <ExpandedView /> : <CollapsedView />}
</div>
</Flipped>
</Flipper>
)
}
- Custom animation:
import { Flipper, Flipped } from 'react-flip-toolkit'
function CustomAnimation() {
return (
<Flipper flipKey={someKey}>
<Flipped
flipId="custom"
onAppear={(el, index) => {
anime({
targets: el,
opacity: [0, 1],
translateY: [20, 0],
delay: index * 100
})
}}
>
<div>Animated element</div>
</Flipped>
</Flipper>
)
}
Getting Started
- Install the package:
npm install react-flip-toolkit
- Import and use in your React component:
import React from 'react'
import { Flipper, Flipped } from 'react-flip-toolkit'
function MyComponent({ items }) {
return (
<Flipper flipKey={items.join('')}>
{items.map(item => (
<Flipped key={item} flipId={item}>
<div>{item}</div>
</Flipped>
))}
</Flipper>
)
}
export default MyComponent
This basic setup will create smooth animations when the items
array changes, automatically handling enter, exit, and move animations for the list items.
Competitor Comparisons
Open source, production-ready animation and gesture library for React
Pros of Motion
- More comprehensive animation toolkit with a wider range of features
- Better documentation and community support
- Seamless integration with Framer Design tool
Cons of Motion
- Larger bundle size, which may impact performance for smaller projects
- Steeper learning curve due to more complex API
Code Comparison
Motion:
import { motion } from "framer-motion"
const Box = () => (
<motion.div
animate={{ x: 100 }}
transition={{ duration: 2 }}
/>
)
react-flip-toolkit:
import { Flipper, Flipped } from "react-flip-toolkit"
const Box = () => (
<Flipper flipKey={someKey}>
<Flipped flipId="box">
<div />
</Flipped>
</Flipper>
)
Summary
Motion offers a more feature-rich animation solution with better documentation and integration with Framer Design. However, it comes with a larger bundle size and potentially more complex API. react-flip-toolkit is more focused on FLIP animations, which can be simpler for specific use cases but may lack some advanced features found in Motion. The choice between the two depends on project requirements, performance considerations, and the desired level of animation complexity.
An easy way to perform animations when a React component enters or leaves the DOM
Pros of react-transition-group
- Well-established and maintained by the React core team
- Simpler API for basic transitions and animations
- Smaller bundle size and fewer dependencies
Cons of react-transition-group
- Limited support for complex animations and FLIP transitions
- Requires more manual work for coordinating multiple elements
- Less performant for large-scale animations
Code Comparison
react-transition-group:
<CSSTransition
in={inProp}
timeout={200}
classNames="fade"
>
<div>Transitioning content</div>
</CSSTransition>
react-flip-toolkit:
<Flipper flipKey={listData}>
<Flipped flipId="list">
<ul>
{listData.map(item => (
<Flipped flipId={item.id} key={item.id}>
<li>{item.name}</li>
</Flipped>
))}
</ul>
</Flipped>
</Flipper>
react-flip-toolkit offers more advanced features for complex animations, especially FLIP transitions, while react-transition-group provides a simpler API for basic transitions. The choice between the two depends on the complexity of animations required in your project.
A spring that solves your animation problems.
Pros of react-motion
- More mature and established library with a larger community
- Provides a physics-based animation system for more natural-feeling animations
- Offers more fine-grained control over animation parameters
Cons of react-motion
- Steeper learning curve due to its physics-based approach
- Can be more verbose and require more setup for simple animations
- Less suitable for complex layout transitions or FLIP animations
Code Comparison
react-motion:
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
{({x}) => <div style={{transform: `translateX(${x}px)`}} />}
</Motion>
react-flip-toolkit:
<Flipper flipKey={someKey}>
<Flipped flipId="box">
<div />
</Flipped>
</Flipper>
react-motion focuses on animating individual properties using physics-based springs, while react-flip-toolkit simplifies complex layout transitions using the FLIP technique. react-motion requires more setup but offers more control, whereas react-flip-toolkit provides an easier API for certain types of animations, particularly layout changes and transitions between different states.
✌️ A spring physics based React animation library
Pros of react-spring
- More comprehensive animation library with a wider range of features
- Better performance for complex animations due to its spring-physics based approach
- Larger community and ecosystem, with more resources and third-party integrations
Cons of react-spring
- Steeper learning curve, especially for developers new to animation concepts
- Can be overkill for simple transitions or FLIP animations
- Slightly larger bundle size due to its extensive feature set
Code Comparison
react-spring:
import { useSpring, animated } from 'react-spring'
function AnimatedComponent() {
const props = useSpring({ opacity: 1, from: { opacity: 0 } })
return <animated.div style={props}>I will fade in</animated.div>
}
react-flip-toolkit:
import { Flipper, Flipped } from 'react-flip-toolkit'
function AnimatedComponent() {
return (
<Flipper flipKey={someKey}>
<Flipped flipId="uniqueId">
<div>I will animate when my position changes</div>
</Flipped>
</Flipper>
)
}
🇨🇭 A React renderer for Three.js
Pros of react-three-fiber
- Specialized for 3D rendering with Three.js integration
- Declarative approach to 3D scene creation
- Large ecosystem and community support
Cons of react-three-fiber
- Steeper learning curve for developers unfamiliar with 3D graphics
- Higher performance overhead for complex 3D scenes
- Limited to 3D animations and not suitable for general UI transitions
Code Comparison
react-three-fiber:
function Box(props) {
const mesh = useRef()
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
useFrame((state, delta) => (mesh.current.rotation.x += 0.01))
return (
<mesh
{...props}
ref={mesh}
scale={active ? 1.5 : 1}
onClick={(event) => setActive(!active)}
onPointerOver={(event) => setHover(true)}
onPointerOut={(event) => setHover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
react-flip-toolkit:
<Flipper flipKey={listData}>
<ul className="list">
{listData.map(item => (
<Flipped key={item.id} flipId={item.id}>
<li>{item.content}</li>
</Flipped>
))}
</ul>
</Flipper>
While react-three-fiber excels in 3D rendering and animations, react-flip-toolkit is more suitable for smooth UI transitions and list animations in 2D space. The choice between the two depends on the specific requirements of the project and the type of animations needed.
🎊 A collection of animations for inline style libraries
Pros of react-animations
- Simpler API, easier to get started with for basic animations
- Provides a set of predefined animations out of the box
- Lightweight and focused solely on CSS animations
Cons of react-animations
- Limited to CSS animations, less flexible for complex scenarios
- Lacks advanced features like FLIP animations or staggered transitions
- May require additional setup for more dynamic animations
Code Comparison
react-animations:
import { fadeIn } from 'react-animations';
import styled, { keyframes } from 'styled-components';
const fadeInAnimation = keyframes`${fadeIn}`;
const FadeInDiv = styled.div`animation: 1s ${fadeInAnimation};`;
react-flip-toolkit:
import { Flipper, Flipped } from 'react-flip-toolkit';
<Flipper flipKey={someKey}>
<Flipped flipId="uniqueId">
<div>Animated content</div>
</Flipped>
</Flipper>
react-animations offers a more straightforward approach for simple animations, while react-flip-toolkit provides more powerful tools for complex, layout-based animations. The choice between them depends on the specific requirements of your project and the complexity of the animations you need to implement.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Comparison with other React FLIP libraries
Feature | react-flip-move | react-overdrive | react-flip-toolkit |
---|---|---|---|
Animate position | â | â | â |
Animate scale | â | â | â |
Animate opacity | â | â | â |
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 | â | â | â |
Quick start
npm install react-flip-toolkit
or yarn add react-flip-toolkit
-
Wrap all animated children with a single
Flipper
component that has aflipKey
prop that changes every time animations should happen. -
Wrap elements that should be animated with
Flipped
components that have aflipId
prop matching them across renders.
Table of Contents
Forkable Examples
Simple Example: An Expanding Div
Fork this example on Code Sandbox
import React, { useState } from 'react'
import { Flipper, Flipped } from 'react-flip-toolkit'
const AnimatedSquare = () => {
const [fullScreen, setFullScreen] = useState(false)
const toggleFullScreen = () => setFullScreen(prevState => !prevState)
return (
<Flipper flipKey={fullScreen}>
<Flipped flipId="square">
<div
className={fullScreen ? 'full-screen-square' : 'square'}
onClick={toggleFullScreen}
/>
</Flipped>
</Flipper>
)
}
Simple Example: Two Divs
Fork this example on Code Sandbox
import React, { useState } from 'react'
import { Flipper, Flipped } from 'react-flip-toolkit'
const Square = ({ toggleFullScreen }) => (
<Flipped flipId="square">
<div className="square" onClick={toggleFullScreen} />
</Flipped>
)
const FullScreenSquare = ({ toggleFullScreen }) => (
<Flipped flipId="square">
<div className="full-screen-square" onClick={toggleFullScreen} />
</Flipped>
)
const AnimatedSquare = () => {
const [fullScreen, setFullScreen] = useState(false)
const toggleFullScreen = () => setFullScreen(prevState => !prevState)
return (
<Flipper flipKey={fullScreen}>
{fullScreen ? (
<FullScreenSquare toggleFullScreen={toggleFullScreen} />
) : (
<Square toggleFullScreen={toggleFullScreen} />
)}
</Flipper>
)
}
Simple Example: List Shuffle
Fork this example on Code Sandbox
import React, { useState } from 'react'
import { Flipper, Flipped } from 'react-flip-toolkit'
import shuffle from 'lodash.shuffle'
const ListShuffler = () => {
const [data, setData] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
const shuffleList = () => setData(shuffle(data))
return (
<Flipper flipKey={data.join('')}>
<button onClick={shuffleList}> shuffle</button>
<ul className="list">
{data.map(d => (
<Flipped key={d} flipId={d}>
<li>{d}</li>
</Flipped>
))}
</ul>
</Flipper>
)
}
List Transitions
Add some interest to a dynamic list of cards by animating changes to cards' sizes and positions.
Fork this example on Code Sandbox
Stagger Effects
The 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
element:
<Flipped flipId={`element-${i}`} stagger>
<AnimatedListItem/>
</Flipped>
Fork this example on Code Sandbox
Spring Customizations
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 flipKey='foo' spring='wobbly'>
{/* Flipped components go here...*/}
</Flipper>
or a custom spring config:
<Flipper flipKey='foo' spring={{ stiffness: 280, damping: 22 }} >
{/* Flipped components go here...*/}
</Flipper>
View all spring options in the interactive explorer
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 flipId={id}>
<div>
<Flipped inverseFlipId={id} scale>
<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 Flipped
container.
Route-based Animations With React Router
react-flip-toolkit
works great with client-side routers to provide route-driven transitions:
<Route
render={({ location, search }) => {
return (
<Flipper
flipKey={`${location.pathname}-${location.search}`}
>
{/* Child routes that contain Flipped components go here...*/}
</Flipper>
)
}}
/>
More examples
The Components
Flipper
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 flipKey={someKeyThatChanges}>{/* children */}</Flipper>
Basic Props
prop | default | type | details |
---|---|---|---|
flipKey (required) | - | string , number , bool | Changing this tells react-flip-toolkit to transition child elements wrapped in Flipped components. |
children (required) | - | node | One or more element children |
spring | noWobble | string or object | Provide a string referencing one of the spring presets — noWobble (default), veryGentle , gentle , wobbly , or stiff , OR provide an object with stiffness and damping parameters. Explore the spring setting options here. The prop provided here will be the spring default that can be overrided on a per-element basis on the Flipped component. |
applyTransformOrigin | true | bool | Whether or not react-flip-toolkit should apply a transform-origin of "0 0" to animating children (this is generally, but not always, desirable for FLIP animations) |
element | div | string | If you'd like the wrapper element created by the Flipped container to be something other than a div , you can specify that here. |
className | - | string | A class applied to the wrapper element, helpful for styling. |
staggerConfig | - | object | Provide configuration for staggered Flipped children. The config object might look something like the code snippet below: |
staggerConfig={{
// the "default" config will apply to staggered elements without explicit keys
default: {
// default direction is forwards
reverse: true,
// default is .1, 0 < n < 1
speed: .5
},
// this will apply to Flipped elements with the prop stagger='namedStagger'
namedStagger : { speed: .2 }
}}
Advanced Props
prop | default | type | details |
---|---|---|---|
decisionData | - | any | Sometimes, you'll want the animated children of Flipper to behave differently depending on the state transition — maybe only certain Flipped elements should animate in response to a particular change. By providing the decisionData prop to the Flipper component, you'll make that data available to the shouldFlip and shouldInvert methods of each child Flipped component, so they can decided for themselves whether to animate or not. |
debug | false | boolean | 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. |
portalKey | - | string | In general, the Flipper component will only apply transitions to its descendents. This allows multiple Flipper elements to coexist on the same page, but it will prevent animations from working if you use portals. You can provide a unique portalKey prop to Flipper to tell it to scope element selections to the entire document, not just to its children, so that elements in portals can be transitioned. |
onStart | - | function | This callback prop will be called before any of the individual FLIP animations have started. It receives as arguments the HTMLElement of the Flipper and the decisionData object described elsewhere. |
onComplete | - | function | This callback prop will be called when all individual FLIP animations have completed. Its single argument is a list of flipId s for the Flipped components that were activated during the animation. If an animation is interrupted, onComplete will be still called right before the in-progress animation is terminated. |
handleEnterUpdateDelete | - | function | By default, react-flip-toolkit finishes animating out exiting elements before animating in new elements, with updating elements transforming immediately. You might want to have more control over the sequence of transitions — say, if you wanted to hide elements, pause, update elements, pause again, and finally animate in new elements. Or you might want transitions to happen simultaneously. If so, provide the function handleEnterUpdateDelete as a prop. The best way to understand how this works is to check out this interactive example. handleEnterUpdateDelete receives the following arguments every time a transition occurs: |
handleEnterUpdateDelete({
// this func applies an opacity of 0 to entering elements so
// they can be faded in - it should be called immediately
hideEnteringElements,
// calls `onAppear` for all entering elements
animateEnteringElements,
//calls `onExit` for all exiting elements
// returns a promise that resolves when all elements have exited
animateExitingElements,
// the main event: `FLIP` animations for updating elements
// this also returns a promise that resolves when
// animations have completed
animateFlippedElements
})
Flipped
Wraps an element that should be animated.
E.g. in one component you can have
<Flipped flipId="coolDiv">
<div className="small" />
</Flipped>
and in another component somewhere else you can have
<Flipped flipId="coolDiv">
<div className="big" />
</Flipped>
and they will be tweened by react-flip-toolkit
.
The 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>
{flippedProps => <MyCoolComponent flippedProps={flippedProps} />}
</Flipped>
const MyCoolComponent = ({ flippedProps }) => <div {...flippedProps} />
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 {...rest} />
Basic props
prop | default | type | details |
---|---|---|---|
children (required) | - | node or function | Wrap a single element, React component, or render prop child with the Flipped component |
flipId (required unless inverseFlipId is provided) | - | string | Use this to tell react-flip-toolkit how elements should be matched across renders so they can be animated. |
inverseFlipId | - | string | Refer to the id of the parent Flipped container whose transform you want to cancel out. If this prop is provided, the Flipped component will become a limited version of itself that is only responsible for cancelling out its parent transform. It will read from any provided transform props and will ignore all other props (besides inverseFlipId .) Read more about canceling out parent transforms here. |
transformOrigin | "0 0" | string | This is a convenience method to apply the proper CSS transform-origin to the element being FLIP-ped. This will override react-flip-toolkit 's default application of transform-origin: 0 0; if it is provided as a prop. |
spring | noWobble | string or object | Provide a string referencing one of the spring presets — noWobble (default), veryGentle , gentle , wobbly , or stiff , OR provide an object with stiffness and damping parameters. Explore the spring setting options here. |
stagger | false | boolean or string | Provide a natural, spring-based staggering effect in which the spring easing of each item is pinned to the previous one's movement. Provide true to stagger the element with all other staggered elements. If you want to get more granular, you can provide a string key and the element will be staggered with other elements with the same key. |
delayUntil | false | string (flipId) | Delay an animation by providing a reference to another Flipped component that it should wait for before animating (the other Flipped component should have a stagger delay as that is the only use case in which this prop is necessary.) |
Callback props
The above animation uses onAppear
and onExit
callbacks for fade-in and fade-out animations.
prop | arguments | details |
---|---|---|
onAppear | element , index , {previous: decisionData, current: decisionData } | 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 onAppear prop, the default opacity of the element will be set to 0 to allow you to animate it in without any initial flicker. If you don't want any opacity animation, just set the element's opacity to 1 immediately in your onAppear function. |
onStart | element , {previous: decisionData, current: decisionData } | Called when the FLIP animation for the element starts. It is provided a reference to the DOM element being transitioned as the first argument. |
onStartImmediate | element , {previous: decisionData, current: decisionData } | Similar to onStart , but guaranteed to run for all FLIP-ped elements on the initial tick of the FLIP animation, before the next frame has rendered, even if the element in question has a stagger delay. It is provided a reference to the DOM element being transitioned as the first argument. |
onSpringUpdate | springValue | 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. |
onComplete | element ,{previous: decisionData, current: decisionData } | 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, onComplete will still be called.) |
onExit | element , index , removeElement , {previous: decisionData, current: decisionData } | Called when the element is removed from the DOM. It must call the removeElement function when the exit transition has completed. |
Transform props
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:
prop | type | details |
---|---|---|
translate | bool | Tween translateX and translateY |
scale | bool | Tween scaleX and scaleY |
opacity | bool |
Advanced props
Functions to control when FLIP happens
prop | arguments | details |
---|---|---|
shouldFlip | previousDecisionData , currentDecisionData | A function provided with the current and previous decisionData props passed down by the Flipper component. Returns a boolean to indicate whether a Flipped component should animate at that particular moment or not. |
shouldInvert | previousDecisionData , currentDecisionData | A function provided with the current and previous decisionData props passed down by the Flipper component. Returns a boolean indicating whether to apply inverted transforms to all Flipped children that request it via an inverseFlipId . |
Spring
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'
spring({
config: "wobbly",
values: {
translateY: [-15, 0],
opacity: [0, 1]
},
onUpdate: ({ translateY, opacity }) => {
el.style.opacity = opacity;
el.style.transform = `translateY(${translateY}px)`;
},
delay: i * 25,
onComplete: () => console.log('done')
});
Global configuration functions
You can programmatically call the following functions if you need to disable (or re-enable) FLIP animations everywhere.
disableFlip()
Global switch to disable all animations in all Flipper
containers.
enableFlip()
Global switch to (re-)enable all animations in all Flipper
containers. Animations are enabled by default. Calling this function is needed only if animations were previously disabled with disableFlip()
.
isFlipEnabled()
Returns a boolean indicating whether animations are globally enabled or disabled.
Library details
- Tested in latest Chrome, Firefox, Safari, and Edge with Browserstack.
- Requires React 16+
- Uses Rematrix for matrix calculations and a simplified fork of Rebound for spring animations
Troubleshooting
Problem #1: Nothing is happening
- Make sure you're updating the
flipKey
attribute in theFlipper
component whenever an animation should happen. - If one of your
Flipped
components 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
Flipped
visible in the DOM?react-flip-toolkit
attempts to optimize performance by not animating elements that are off-screen or elements that have no width or height. display:inline
elements cannot be animated. If you want aninline
element to animate, setdisplay:inline-block
.- Do you have the prefers-reduced-motion setting turned on? As of v7.1.0 that setting will disable all animations.
Problem #2: Things look weird / animations aren't behaving
- Check to make sure all
flipId
s are unique. At any point, there can only be one element with a specifiedflipId
on the page. If there are multipleFlipped
elements 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 aninline-block
style 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
debug
prop. If you still can't figure out what's going wrong, you can add the thedebug
prop directly on yourFlipper
component to pause transitions at the beginning. - If you think something might actually be broken, or are completely stuck, feel free to make an issue.
Performance
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.
Memoization
When you trigger a complex FLIP animation with react-flip-toolkit
, 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 React.memo
or 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.
will-change:transform
.box {
will-change: transform;
}
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, try seeing if it increases the performance of the animation.
Top Related Projects
Open source, production-ready animation and gesture library for React
An easy way to perform animations when a React component enters or leaves the DOM
A spring that solves your animation problems.
✌️ A spring physics based React animation library
🇨🇭 A React renderer for Three.js
🎊 A collection of animations for inline style libraries
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot