I am not sure if this is the proper place to ask this question; I considered Software Recommendations however I figured I'd give it a shot here first.
I am creating a PWA and with every iteration I'd really like to focus on making it look/feel like less janky and as smooth as possible. Well, like a native app.
So here is the problem—I am using transitions (animations) provided by Semantic-UI-React, and while it works beautifully when an element which is occupying its on space, I was wondering if there a practice or pattern which handles the behavior of adjacent DOM elements to one that is being animated?
I supplied a GIF below to illustrate what I mean. I suppose I could just move the animated elements out of the container of the form to prevent jank, but I wondered if there was a more elegant pattern or approach to this...
Merci!
Unfortunately, there is no particularly elegant approach to this.
Regarding the question in the title of your post, a common approach is to animate the
height
of the new elements. If you don't know the height of the elements, unfortunately animating from0px
toauto
does not yet work but you can fudge it by animatingmax-height
from0px
to a value slightly larger than the maximum size you expect the element to be.But don't do that.
It will cause the browser to layout the page on every animation frame and will almost certainly jank on lower-end devices.
Instead, you're better off to animate
transform
.The most common approach is to:
Grab the original position of the elements (using
getBoundingClientRect()
etc.) that are going to be affected just before you add the new elements to the DOM (perhaps usinggetSnapshotBeforeUpdate
unless you're using hooks, in which case you can useuseRef
to similar effect).After you've added the new elements (which you're presumably also animating in by using
transform
with a suitablescale()
function), calculate the delta from where the offset elements are now, compared to where they used to be.Setup a
transform
animation from the negative of the delta, to zero (i.e. the FLIP approach). E.g. if the element has been shifted 300px down the page, animatetransform
fromtranslateY(-300px)
tonone
.Of course you need to do that for all the elements in the flow that are affected so it might be easiest to put them all in one container and just animate that.
Regarding the third point you have a few choices of technology, none of which are great:
CSS transitions. These are simplest but you'll have to trigger a style flush to get the negative delta starting point to stick. e.g.
CSS animations. Producing
@keyframes
rules dynamically using the CSSOM is a pain but at least you don't need to trigger a style flush (and you can set an animation with an implicit to-keyframe for convenience).Web animations. This is probably the most well-suited.
Unfortunately Safari only has Web Animations support in Tech Preview so Safari users will get the un-animated version until the next Safari release. Edge users will also get the un-animated version until the Chromium based Edge ships. There is a polyfill too but it's not actively maintained at this point in time.
If you're using React, Animating the Unanimatable is a helpful article on all this.
The other tricky part is making sure the scroll doesn't jump for which you might need to look into scroll anchoring.