framer / motion

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

[BUG] Reduced motion causes flashing elements if custom css exists for reduced motion as well #2153

Closed IDrumsey closed 1 year ago

IDrumsey commented 1 year ago

Describe the bug

Framer motion animations "flash" when using with custom reduced motion css.

See https://stackoverflow.com/questions/76314970/framer-motion-animations-flashing-when-used-in-conjunction-with-custom-css

IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/p/sandbox/nervous-leaf-wblzxc

Steps to reproduce

Steps to reproduce the behavior: See stack

Expected behavior

The animations should NOT flash.

Environment details

Happens in Firefox and I think Safari (Haven't tested sandbox in Safari)

mattgperry commented 1 year ago

The second line doesn't flash because the line doesn't move. The first line flashes because the hit area is moving under and away from the mouse in an infinite loop.

The hover event/styles should be applied to a hitbox that stays static the whole time.

Read more: https://www.joshwcomeau.com/animation/css-transitions/#doom-flicker-13

IDrumsey commented 1 year ago

Update: Have changed from lines to boxes to fix hover issues.

Perhaps I should have been more clear, but that was not the issue I was referring to. The second line element flashes when reduced motion is turned on. I know what's causing it at a surface level. It's the custom css reduced motion line transition-duration: 0.001ms !important;. If you comment that out in globals.scss the flash goes away. But the issue with that solution is that I need that css to prevent NON framer motion elements (like the first horizontal line) from having motion in their animations. One solution might be to somehow apply the effects of the <MotionConfig reduced="user"> wrapper to all children, not just the framer motion children, but I don't think that is possible.

https://github.com/framer/motion/assets/58646634/1bfeb604-70dc-4e36-b921-8546de84d13a

Here's another sandbox that shows the issue if you remove the custom reduced motion css. WIth reduced motion turned on, you'll notice that the animation for the framer element doesn't have motion, but the non-framer element still does. So now the flash is fixed, but the motion on regular elements has become the new issue.

https://github.com/framer/motion/assets/58646634/0ed319ba-0759-47ed-86c3-d51eea32d7e9

IDrumsey commented 1 year ago

Investigating a little further, adding the line transition-duration: 5s !important;, the box runs the animation/transition twice (which is why we see a flash with 0.001ms for the duration instead of 5s). It seems like it runs first with Framer's default transition duration and then runs again with our custom duration. As discussed in this video, the custom css where the custom duration comes from is an easy way to reduce the motion for all elements. I don't want to have to go in and reduce the motion for all the animations in the codebase if possible. @mattgperry can we reopen this as this is likely a bug with framer?

https://github.com/framer/motion/assets/58646634/f1a6cbfa-1916-4500-9ba3-a21a45211965