joshwcomeau / react-flip-move

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.
http://joshwcomeau.github.io/react-flip-move/examples
MIT License
4.09k stars 258 forks source link

Animations with position:sticky / scroll position update #141

Closed agido-freudenreich closed 7 years ago

agido-freudenreich commented 7 years ago

Hi,

i'm currently trying to add sticky headers to a large list of elements. Due to position: sticky the animations get broken / look weird. Is there a workaround to handle these kinds of elements? Maybe by setting the position temporarily to relative during the animation phase?

And another question regarding the scroll position: I use react-flip-move to sort "favorite" items to the top of a list. Sometimes (but only sometimes) the scroll position is updated accordingly and "follow" the clicked item. Is there an option / fix to ensure that the scroll position is always updated or do i have to manage it outside of the library? I'm willing to add it by myself if it makes sense :smile:

Thanks in advance and for this nice library :+1:

joshwcomeau commented 7 years ago

Hey @obituz,

Hm, I haven't done any testing with position: sticky. If you could create a story in the stories directory that showcases the issue (in github-issues.stories.js), it'll help me poke around with it :)

That said, I'm at an airport now, heading to the states for a few days for a wedding, so it's unlikely that I'll be able to tackle this shortly.

As for updating scroll position to follow the item, hm. I think the easiest way to do it would be to handle it on your end. Presuming you have some method that calls setState to update the list of items (or dispatches a redux action, whatever), you could just scroll the user to the top of the list?

I'd rather not move that logic into FlipMove itself since it's fairly niche (haven't seen any requests for it yet), and I feel like it would complicate the code quite a bit.

agido-freudenreich commented 7 years ago

Hi @joshwcomeau,

added the story in #143. I think the "shuffle" command shows the animation problem. Thanks for your help.

joshwcomeau commented 7 years ago

Awesome, thanks @obituz.

At first I thought the issue was that it was really glitchy and stuttery, but that turned out to just be because there were so many items. By reducing it to 20 items, I think I have a better understanding of the issue.

I think the issue is either a complication between position: sticky and getBoundingClientRect, a complication between position: sticky and transform: translate, or both.

I think that because looking closely when using the rotate option in the story, the sticky item appears to instantly jump down by ~50% of its height, and then transitions into its proper position. The newly-becoming-sticky item starts at the same point as the formerly-sticky item, but it transitions up by 50% to take the spot.

This is a really weird interaction, and it could be explained either by getBoundingClientRect not returning an accurate value for sticky items, or by transform: translate working differently for stuck items.

Unfortunately it doesn't seem like a quick fix :( If this animation is important to you, I'd suggest trying to manage the stickiness manually using javascript and position: absolute. I know that's a bummer though.

agido-freudenreich commented 7 years ago

Hi @joshwcomeau,

sorry for my late answer. Thanks for your help and the explanation. We'll try to either manage it by manually stickyness or leave it out. You/PM can't have everything ;)

agido-freudenreich commented 7 years ago

Hi @joshwcomeau,

quick update, also for people who have the same issue: I've managed it with a little (hack) function to calculate the "real" top position and set it as getPosition prop.

getPosition = node =>{
    const position = window.getComputedStyle(node).position;
    node.style.position = 'relative';
    const boundingClientRect = node.getBoundingClientRect();
    node.style.position = position;
    return boundingClientRect;
}
bolaum commented 6 years ago

@obituz dude, you're my hero <3