Gesture Animations
With the whileHover
, whileTap
, and whileDrag
gesture animations, you can quickly make layers interactive. With just one line of code, you add an automatic animation between two states.
While Hover
Here’s an override example: You give
an object with the properties you want to animate, just like we did earlier with animate
.
export function WhileHover(Component): ComponentType {
return (props) => {
return <Component {...props} whileHover={{ scale: 0.8 }} />
}
}
The frame shrinks to 80 percent of its size when you hover over
With one line of code, you’ve added two animations:
- one that happens when the pointer is over the frame;
- and a reverse animation that runs when the pointer leaves the frame.
While Tap
The second one, whileTap
, works the same, but for tap gestures.
export function WhileTap(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
whileTap={{ scale: 0.8 }}
transition={{ duration: 0.5 }}
/>
)
}
}
And just like with animate
, you can tweak these animations by adding transition
settings. For example, here, the frame will take its sweet little time of half a second to shrink when you press down. And the same thing happens when you release; the grow animation also has a duration
of 0.5
.
While Drag
Framer Motion 3 added a whileDrag
interaction. It works as you would expect.
Naturally, you can combine these gesture animations. Here we have a draggable frame with whileHover
, whileTap
, and whileDrag
:
export function WhileDrag(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
drag
whileHover={{ opacity: 1 }}
whileTap={{
opacity: 1,
scale: 1.05,
boxShadow: "0px 5px 8px #037",
}}
whileDrag={{ scale: 1.1, boxShadow: "0px 10px 16px #037" }}
transition={{ duration: 0.6 }}
/>
)
}
}
whileHover
— I gave the frame an opacity of 70% on the canvas, which changes to 100% when you hover over it.whileTap
— Tapping the frame makes it grow slightly (scale
of 105%) and gives it a shadow.whileDrag
— Once you start dragging, it seems to float a bit higher above the surface because of itsscale
of 110% and a largerboxShadow
.
(The whileTap
also changes the opacity
to 1
. This is for touch devices, on which a whileHover
is not triggered.)
All three animations have a duration of 0.6
seconds, a bit longer than the default 0.3
.
While Focus
Framer Motion 3.1 added whileFocus
. Only HTML input elements can have a focus state, so you have to use a <motion.input>
.
I tried to make something that’s impossible with CSS’s :focus
pseudo-class and arrived at this crazy background animation that cycles through keyframes of different gradients.
export function C04WhileFocusFM() {
return (
<motion.input
style={{
// width, background, etc.
}}
whileFocus={{
background: [
"linear-gradient(to right, #f0f -200%, #0ff -100%, #f0f 0%, #0ff 100%)",
"linear-gradient(to right, #f0f -100%, #0ff 0%, #f0f 100%, #0ff 200%)",
"linear-gradient(to right, #f0f 0%, #0ff 100%, #f0f 200%, #0ff 300%)",
],
}}
transition={{
background: {
duration: 2,
repeat: Infinity,
ease: "linear",
from:
"linear-gradient(to right, #fff -200%, #fff -100%, #fff 0%, #fff 100%)",
},
}}
/>
)
}
(Apparently, adding the from
value keeps it from continuing to animate (in Framer) when the input field has already lost focus.)
whileFocus
with validation example
In the tweet announcing whileFocus
, Matt Perry added this example that gives a visual indication of the field’s validation status:
- Blue: Neutral
- Green: Valid value entered
- Red: Invalid value entered (no spaces allowed!)
It has an onBlur()
event (called when the element loses focus) that changes a validity
state, which, in turn, defines which color is used for the boxShadow
around the field.