React-modal: Prevent Body Scrolling (iOS)

Created on 14 Oct 2020  路  9Comments  路  Source: reactjs/react-modal

There a lot of threads online about how to lock the body especially on iOS, but I haven't found a good answer.

body {
overflow: hidden;
}
Doesn't work on iOS.

My question is: how can I prevent Body Scrolling on iOS with react-modal?

Note: I found this package that it might work, but the problem is that I can't find a way to make it work with react-modal and hooks. React Modal doesn't accept a ref using useRef.

https://github.com/willmcpo/body-scroll-lock

Any help?

Most helpful comment

Simple solution would be 馃憤

onAfterOpen={() => document.body.style.overflow = 'hidden'}
onAfterClose={() => document.body.style.overflow = 'unset'}

All 9 comments

hello @Alfrex92!

You can try

body{
overflow: hidden;
position: fixed;
width: 100%;
height: 100%;
}

but, this will generate a side effect on the scroll, leading to the beginning of the page whenever the modal is open.

Thanks jrmarqueshd! any other idea?

@Alfrex92 you could try this.

<ReactModal
  onAfterOpen={() => {
    document.body.style.top = `-${window.scrollY}px`
    document.body.style.position = 'fixed'
  }}
  onAfterClose={() => {
    const scrollY = document.body.style.top
    document.body.style.position = ''
    document.body.style.top = ''
    window.scrollTo(0, parseInt(scrollY || '0') * -1)
  }}
  ...other props
/>

I use this way:

import React, { forwardRef, useRef, useImperativeHandle } from 'react'
import ReactModal from 'react-modal'
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'

const Modal = forwardRef(({ children, ...props }, ref) => {
    const modalRef = useRef()

    useImperativeHandle(ref, () => modalRef.current, [modalRef])

     const modalProps = {
       onAfterOpen: () => disableBodyScroll(modalRef.current),
       onAfterClose: () => enableBodyScroll(modalRef.current),
       ref: modalRef,
       ...props,
     }

    return (
      <ReactModal {...modalProps}>
        {children}
       </ReactModal>
     )
})

Simple solution would be 馃憤

onAfterOpen={() => document.body.style.overflow = 'hidden'}
onAfterClose={() => document.body.style.overflow = 'unset'}

@ursNj thanks, your solution works on iPhone and Android. But, there is a small issue on Android:

https://imgur.com/a/wS3903x

As you can see the body is not being scrolled but there is a small issue.

@Alfrex92 I have tested this solution on android and web both the places it was working fine, i think your issue is not with scrollbar but chrome browser.

As per my understanding even your code should work fine in web, but not mobile because mobile chrome browser has URL bar, but when you scrollup that bar will go, due to this you are feeling still you have some issue.

You can see same on this app: https://www.watchpartys.com

@ursNj
I tested on Firefox and it's the same issue 馃槩

These are my styles

const customStyles = {
  overlay: {
    background: 'rgba(0, 0, 0, 0.8)',
    zIndex: zindex.modal
  },
  content: {
    border: 'none',
    padding: 0,
    overflow: 'unset',
    backgroundColor: 'unset',
    width: '100%',
    height: '100%',
    inset: '0',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    top: 0,
    right: 0,
    left: 0,
    bottom: 0
  }
}

I found a code that doesn't have the issue but I don't know how to implement it to React Modal
https://codepen.io/maladr0it/pen/LYpOJgV

thanks a lot for the help 馃槂

Hey
if you look at it carefully its due to the nav bar up top by the browser popuping up
thats out of out control unless you set widths to be strictly based on pixel

Was this page helpful?
0 / 5 - 0 ratings