framer / motion

Open source, production-ready animation and gesture library for React
https://framer.com/motion
MIT License
22.41k stars 740 forks source link

[BUG] layoutId has incorrect positioning when height adjusts. #1972

Open Looskie opened 1 year ago

Looskie commented 1 year ago

When underlying children have height adjustments, layoutId seems to not know where to go and results in a weird and inconsistent animation.

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug https://codesandbox.io/p/sandbox/framer-motion-layoutid-issue-uu7kb9?selection=%5B%7B%22endColumn%22%3A13%2C%22endLineNumber%22%3A88%2C%22startColumn%22%3A13%2C%22startLineNumber%22%3A88%7D%5D&file=%2Fsrc%2FApp.tsx

(I even added a button with a "work-around", but the work-around is not the preferred way of fixing it (especially in my use case where I'm rendering pretty hefty components)

WORKAROUND: https://github.com/framer/motion/issues/1972#issuecomment-1483452870

4. Steps to reproduce

Check sandbox and switch through tabs

5. Expected behavior

The underline should stay in its place and not animate off to the ends

6. Video or screenshots

what its NOT supposed to do

https://user-images.githubusercontent.com/50378828/220939076-118561cf-b8a2-45e5-8ec5-84532f774382.mov

what its SUPPOSED to do

https://user-images.githubusercontent.com/50378828/220937849-fe5a55ff-54d5-43ce-8672-96dd066d8715.mov

7. Environment details N/a

hexiro commented 1 year ago

I'm experiencing this same issue when the layoutId components are position: fixed and the page scrolls. This could be caused by the same mechanic under the hood, but regardless, it produces an undesired effect with the Y values animating.

hexiro commented 1 year ago

workaround: codesandbox

image

the patch is on line 48 and works by setting originY to 0px, which effectively disables the Y value from shifting during the animation.

Sebastian-Nielsen commented 3 months ago

workaround: codesandbox

image

the patch is on line 48 and works by setting originY to 0px, which effectively disables the Y value from shifting during the animation.

You can't use this solution if your layoutId animation is animating vertically. (E.g. imagine your example but the tabs were stacked vertically).

Does anyone know of a solution to that?

Looskie commented 3 months ago

workaround: codesandbox image the patch is on line 48 and works by setting originY to 0px, which effectively disables the Y value from shifting during the animation.

You can't use this solution if your layoutId animation is animating vertically. (E.g. imagine your example but the tabs were stacked vertically).

Does anyone know of a solution to that?

Using:

style={{ originX: 0 }} // use originX instead of originY 

on the animated item should help you in your case, given that you're not animating both horizontally and vertically. Take a look at this sandbox to see if this suits your case: codesandbox

The only issue with this workaround really is if you want both originX and originY movement... Which in that case is the reason this issue is still open!

Sebastian-Nielsen commented 3 months ago

workaround: codesandbox image the patch is on line 48 and works by setting originY to 0px, which effectively disables the Y value from shifting during the animation.

You can't use this solution if your layoutId animation is animating vertically. (E.g. imagine your example but the tabs were stacked vertically). Does anyone know of a solution to that?

Using:

style={{ originX: 0 }} // use originX instead of originY 

on the animated item should help you in your case, given that you're not animating both horizontally and vertically. Take a look at this sandbox to see if this suits your case: codesandbox

The only issue with this workaround really is if you want both originX and originY movement... Which in that case is the reason this issue is still open!

I would like to animate in both the y- and x-axis direction, so that won't work.

piersolenski commented 3 months ago

I was hacking at this for days until I found this issue, I need to animate both the y and x direction, this is a real blocker 🫠

JJozef commented 1 month ago

I was hacking at this for days until I found this issue, I need to animate both the y and x direction, this is a real blocker 🫠

this worked for me, I don't know if you still need it hahaha

<motion.div
    layoutId='button'
    initial={false}
    style={{
      transition: 'backdrop-filter 500ms ease 0s',
      originY: '0px' // <----- here
    }}
    className='pointer-events-none absolute bottom-0 z-10 h-px w-full rounded-lg border-b-2 border-zinc-950 dark:border-white'
    transition={{
      type: 'spring',
      stiffness: 120 / SPEED,
      damping: 20,
      mass: 1
    }}
  />
kKaskak commented 1 month ago

I was hacking at this for days until I found this issue, I need to animate both the y and x direction, this is a real blocker 🫠

this worked for me, I don't know if you still need it hahaha

<motion.div
    layoutId='button'
    initial={false}
    style={{
      transition: 'backdrop-filter 500ms ease 0s',
      originY: '0px' // <----- here
    }}
    className='pointer-events-none absolute bottom-0 z-10 h-px w-full rounded-lg border-b-2 border-zinc-950 dark:border-white'
    transition={{
      type: 'spring',
      stiffness: 120 / SPEED,
      damping: 20,
      mass: 1
    }}
  />

This works, but it's just one dimensional. IF you have a multidimensional animation it won't work.