Feature | react-flip-move |
react-overdrive |
react-flip-toolkit |
---|---|---|---|
Animate position | ✅ | ✅ | ✅ |
Animate size | ❌ | ✅ | ✅ |
Animate parent's size without warping children | ❌ | ❌ | ✅ |
Use real FLIP instead of cloning & crossfading | ✅ | ❌ | ✅ |
Enable nested animations | ❌ | ❌ | ✅ |
Easy to set up/beginner-friendly | ✅ | ✅ | 🤷 |
- Guitar shop
- Menu with nested transitions
- Simplest possible example
- Absurd overly complex example
- React-flip-toolkit logo animation
- Sort & Filter
If you need a refresher, here's an article by the person who created FLIP: Flip Your Animations
npm install react-flip-toolkit
- Wrap your container element with a
Flipper
component that has aflipKey
prop that changes every time an animation should happen. - Wrap elements that should be animated with
Flipped
components that haveflipId
props matching them across renders.
import { Flipper, Flipped } from "react-flip-toolkit"
const colors = ["#ff4f66", "#7971ea", "#5900d8"]
class Container extends Component {
state = { focused: undefined }
render() {
return (
<Flipper flipKey={this.state.focused}>
<main>
{typeof this.state.focused === "string" ? (
<Flipped flipId={this.state.focused}>
<div
className="focusedItem"
style={{ backgroundColor: this.state.focused }}
onClick={() => this.setState({ focused: null })}
/>
</Flipped>
) : (
<ul className="list">
{colors.map(color => (
<Flipped flipId={color}>
<li
className="listItem"
style={{ backgroundColor: color }}
onClick={() => this.setState({ focused: color })}
/>
</Flipped>
))}
</ul>
)}
</main>
</Flipper>
)
}
}
In this example, all Flipped
elements are direct children of the Flipper
parent component, but in many cases they will be contained in different components.
The parent wrapper component that contains all the elements to be animated:
<Flipper flipKey={someKeyThatChanges}>
{/* children wrapped in Flipped components*/}
</Flipper>
- required:
flipKey
: (string
,number
,bool
) Changing this tellsreact-flip-toolkit
to transition child elements wrapped inFlipped
components. - required:
children
: (node
) One or more element children ease
: (string
, default:easeOut
) Default easing for all FLIP transitions. This string should refer to one of the easings provided by Popmotion, see the full list hereduration
: (number
, default:250
) Default duration in ms for all FLIP transitions.applyTransformOrigin
: (bool
, default:true
) Whether or notreact-flip-toolkit
should apply a transform-origin of "0 0" to animating children (this is generally desirable for FLIP animations)
A component that wraps an element that needs to be animated:
<Flipped flipId="coolDiv">
<div>animate me</div>
</Flipped>
- required:
children
: (node
) you have to wrap a single child with theFlipped
component. If the child is a React component, make sure it passes down unknown props directly to the rendered DOM element so thatFlipped
can pass down the necessarydata-*
attributes. - required:
flipId
: (string
) Use this to tellreact-flip-toolkit
how elements should be matched across renders so they can be animated. E.g. in one component you can have
<Flipped flipId="coolDiv">
<div className="small" />
</Flipped>
and in another you can have
<Flipped flipId="coolDiv">
<div className="big" />
</Flipped>
and they will be tweened by react-flip-toolkit
inverseFlipId
: (string
) refer to the id of the parentFlipped
container whose transform you want to cancel out. Read more about canceling out parent transforms heretransformOrigin
: (string
, like"50% 100%"
) this is a convenience method to apply the proper CSStransform-origin
to the element being FLIP-ped. This will overridereact-flip-toolkit
's default application oftransform-origin: 0 0
if it is provided as a prop.ease
: (string
) This string should refer to one of the easings provided by Popmotion, see the full list here. This will override the one specified in the parentFlipped
component.duration
: (number
) Timing for the individual FLIP transition, this will override the one specified in the parentFlipped
componentdelay
: (number
) Amount of time to wait before tweening the element position.onAppear(element)
: (func
) called when the element first appears. 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.onStart(element)
: (func
) called when the FLIP animation starts. It is provided a reference to the DOM element being transitioned as the first argumentonComplete(element)
: (func
) called when the FLIP animation starts. 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.)
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:
translate
: (bool
) TweentranslateX
andtranslateY
scale
: (bool
) TweenscaleX
andscaleY
opacity
: (bool
)
componentId
: (string
) Identify the componentcomponentIdFilter
: (string
) Only apply FLIP transitions if the transition originates or ends with a component with the specifiedcomponentId
Some other FLIP libraries just allow you to animate position changes, but things get a lot more interesting once you can animate scale changes as well (check out the demos to see what scale animations bring to the table).
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={parentFlipId}>
<div>
<Flipped inverseFlipId={parentFlipId} scale>
<div>some text that will not be warped</div>
</Flipped>
</div>
</Flipped>
By default, not only the scale of the parent will be counteracted, but also the translations (this allows children components to make their own FLIP animations without being affected by the parent).
But for many/most 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.
- ~8kb minified and gzipped
- Requires React 16+
- Tested in latest Chrome, Firefox, Safari + Edge
- Q: I set up the animations but nothing is animating
- A: Make sure you're updating the
flipKey
attribute in theFlipper
component whenever an animation should happen.