RFC: sizeTransition
See original GitHub issueOverview
A motion
prop for HTML elements, sizeTransition
, that enables content to animate between layout sizes.
Mirroring positionTransition
, sizeTransition
would animate components when they change width
/height
as the result of a re-render.
<motion.div sizeTransition>
<Content />
</motion.div>
Use-case(s)
- Tabbed content
- Accordions
- Modals
Proposal
sizeTransition
can be defined either a boolean:
<motion.div sizeTransition />
or a Transition
:
<motion.div sizeTransition={{ duration: 1 }} />
Release 1: width
/height
In the first iteration, it’ll animate width
and height
from their previous to their new measured dimension.
Release 2: scaleX
/scaleY
By default, animating width
and height
will trigger layout. This can be slow and is better avoided for consistent 60fps animations. A more performant way would be animate scale
.
This will necessitate either an inversion prop or component that can “undo” the scaling effect (so only the container visually scales).
Prop:
<motion.div sizeTransition>
<motion.div invertScale>{contents}</motion.div>
</motion.div>
Component:
<motion.div sizeTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
At parent scale
s of < ~0.05 - ~0.1 we can fade this element out to prevent scaling to Infinity
.
Is the presence of an inversion prop/component a pre-requisite to enable the scale
performance animation? And/or the signal to use scale
over width
/height
?
Release 3: Interactions with positionTransition
(prospective)
width
and height
will naturally reflow-components every frame, but it isn’t performant. But scale
doesn’t effect layout, so its surrounding components would “jump” into their new layout.
It’d be good if at least sibling components could respond to each other’s scale
resizing with a co-ordinated animation. So for instance this code:
<motion.div style={{ height: isOpen ? 'auto' : 0 }} sizeTransition positionTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
<motion.div style={{ height: isOpen ? 'auto' : 0 }} sizeTransition positionTransition>
<InvertScale>{contents}</InvertScale>
</motion.div>
As one component animate in size via scale
, its surrounding components would animate in position using x
/y
.
Framer X considerations
As sizing isn’t abstracted the way positional layout is to x/y, this should drop-in to Frame
. Animating the position of surrounding components would require them to be in a DOM layout, ie Stack
.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:19
- Comments:17 (2 by maintainers)
Top GitHub Comments
Ah yeah I should have added a note. The WIP branch is now
feature/layout-transition
In that instance the parent animation wouldn’t be triggered because sizeTransition only measures changes in height as the result of a re-render. Which would be the one state change of the expanded comments.
Even so, this isn’t going to be an issue in any event as I’ve been prototyping and I’m going skip the first step of animating width and height. I saw the accordion in action after making it and it’s ok but the results from scale will be much smoother.