Modal with FloatingFocusManager and no autoFocus scrolling to top of page
rob-johansen opened this issue · comments
Describe the bug
I'm using FloatingFocusManager
with nothing on my modal that has autoFocus
, yet the page scrolls to the top when the modal is opened—and scrolls back down when the modal is closed.
To Reproduce
I'm sorry that I cannot reproduce the problem in a codesandbox, but I'm sharing links to my code (hopefully the next best thing):
- Here is my Modal component
- And here is an example of how a component renders an instance of my Modal
Expected behavior
The page does not scroll when my Modal is opened
Video
floating-ui.mov
Context:
- OS: macOS Sonoma 14.3
- Browser: Brave
- Version: @floating-ui/react v0.25.4
Additional context
I thought maybe it had something to do with conditionally rendering my modals from outside, but I tried moving the isOpen
state management inside the modal with useState()
but it didn't make a difference.
Version: @floating-ui/react v0.25.4
This is a bit old. What about the latest 0.26.13
?
The lockScroll
on FloatingOverlay
could be a problem. What happens if it's removed? Without a minimal reproduction, it's hard to debug this though.
I updated to 0.26.13
and the problem persists. I've been able to track it down to either lockScroll
or this CSS:
html, body {
height: 100%;
}
The problem goes away if I either comment that CSS out, or remove lockScroll
. Unfortunately I still can't reproduce it in a code sandbox because my project is so complex.
I just figured out the true problem:
html {
overflow-y: scroll;
}
The sad part is that I have no idea why I ever added that (it was lurking at the bottom of my global CSS file). 🤦♂️
Sorry for wasting your time, but if someone else runs into this hopefully they can learn from my mistake.
FWIW, I was able to reproduce it in this code sandbox:
It's probably good to mention this potential issue under a Troubleshooting
section for FloatingOverlay
docs then 👍
I quickly discovered why I had added that CSS! It prevents layout shift in scenarios like these:
- A page goes from loading, where no scrollbar is present, to showing enough content that a scrollbar appears (see this example from Josh Comeau)
- You simply navigate from a page in your app that has no scrollbar (not much content), to another page in your app that does have a scrollbar (and now your nav, for example, shifts the width of the scrollbar)
So now I've added the CSS back, along with this little "fix" at the top of my Modal
component:
useEffect((): () => void => {
document.documentElement.style.overflowY = 'unset'
return (): void => {
document.documentElement.style.overflowY = 'scroll'
}
}, [])