floating-ui / floating-ui

A JavaScript library to position floating elements and create interactions for them.

Home Page:https://floating-ui.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

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'
  }
}, [])