react-modal icon indicating copy to clipboard operation
react-modal copied to clipboard

Don't scroll parent component when Modal is opened

Open rahulthewall opened this issue 8 years ago • 51 comments

Summary: Don't scroll parent component when Modal is opened

Steps to reproduce:

  1. Implement a Modal
  2. Open the Modal
  3. The parent component of the Modal is still scrollable while the Modal is open

Expected behavior: The Component that calls the Modal should not be scrollable when the Modal is opened.

Is there any way I can change this?

rahulthewall avatar Jun 24 '16 09:06 rahulthewall

@rahulthewall there is an callback called onAfterOpen. you can install a callback to disable the desired element.

diasbruno avatar Jul 01 '16 18:07 diasbruno

@rahulthewall Or in CSS, something like:

.ReactModal__Body--open {
  overflow-y: hidden;
}

Which will prevent overflow-y on the body whilst the modal is open.

emmerich avatar Jul 05 '16 12:07 emmerich

Hello @diasbruno @emmerich ,are your solutions work arounds or best / common practices ?

Is the CSS going to work in all browsers ? I don't really know this syntax, but it's working with sass ?

amangeot avatar Jul 30 '16 09:07 amangeot

@amangeot sometimes you need to change the behaviour of your application because of an event X. so it's an ok solution.

@emmerich's css class, .ReactModal__Body--open, is defined by the react-modal, but it has no effect because this rule is not defined by react-modal. It's not defined because if you want the oppose behaviour you would need to be more hacky overriding the .ReactModal__Body--open rule to let the page scroll.

you can use afterOpen which is the programmatically way and you can attach a css class to any element.

diasbruno avatar Jul 30 '16 14:07 diasbruno

...if it's a cross-browser solution, you always need to test. A good place to check which browsers implements this feature is Mozilla's MDN CSS MDN overflow-y

diasbruno avatar Jul 30 '16 15:07 diasbruno

@amangeot overflow-y works with all browsers and I assume React Modal works with the same browser set as React.

@diasbruno I didn't understand this: .ReactModal__Body--open, is defined by the react-modal, but it has no effect because this rule is not defined by react-modal.. Could you clarify? Not sure what the problem is with using a class defined by React Modal for React Modal-specific behaviour.

emmerich avatar Jul 31 '16 20:07 emmerich

gee, that was a very bad explanation...sorry.

.ReactModal__Body--open class is added to the body element by react-modal, but the class itself is not defined.

diasbruno avatar Jul 31 '16 21:07 diasbruno

Is there another workaround for this? I would like the parent component not to be scrollable while preserving the page scroll

carlows avatar Aug 27 '16 18:08 carlows

nevermind, just need to set position: absolute for the element instead of position: fixed

carlows avatar Aug 27 '16 18:08 carlows

I'm closing this issue for clean up. Thank you all for the tricks, hope we can publish this on the docs.

diasbruno avatar Feb 16 '17 01:02 diasbruno

For this to work on iOS position, width and height are also necessary:

.ReactModal__Body--open {
  overflow: hidden;
  position: fixed;
  width: 100%;
  height: 100%;
}

However this will cause the page to jump to the top on modal open.

AlecRust avatar May 17 '17 17:05 AlecRust

I'm facing exactly this same issue but only for IOS. The overflow hidden on the body works just fine for the others platforms though. Does anyone found a good solution that doesn't have backfires like the position going to the top after the modal being opened?

kaiomagalhaes avatar Aug 06 '17 14:08 kaiomagalhaes

@kaiomagalhaes only to use react-aria-modal instead.

AlecRust avatar Aug 06 '17 15:08 AlecRust

I am also looking for a solution to the position of the parent page scrolling to the top when the modal is opened.

wiggitamoo avatar Sep 29 '17 16:09 wiggitamoo

@wiggitamoo I've gone with @AlecRust solution, the other react modal does't have this issue.

kaiomagalhaes avatar Sep 29 '17 17:09 kaiomagalhaes

Thanks @AlecRust, I'll use this modal as well.

watch-janick avatar Apr 01 '18 14:04 watch-janick

hey tried parent { overflow: hidden; position: fixed; width: 100%; height: 100%; }

Unfortunately it also stops the parent from scrolling completely. @diasbruno This is ios only issue. onAfterOpen will still scroll the background if i do it like this:

<Modal isOpen={open} onRequestClose={this.handleCloseModal} style={styles.modal} contentLabel="Example Modal" onAfterOpen={this.disableScroll} >

and then my disableScroll is defined like this

disableScroll = () => { document.body.style.overflow = 'hidden' }

kevinzhangftw avatar May 31 '18 20:05 kevinzhangftw

@ wiggitamoo

I am also looking for a solution to the position of the parent page scrolling to the top when the modal is opened.

This thread is quite old, but in case it's helpful to others, I found that the way to prevent this issue is to set top, right, bottom, and left to zero:

overflow: hidden; position: fixed; top: 0; right: 0; bottom: 0; left: 0;

mbrowne avatar Jun 04 '18 21:06 mbrowne

@mbrowne does it solve for when you need to scroll the content of the modal?

kaiomagalhaes avatar Jun 05 '18 02:06 kaiomagalhaes

As long as the container holding your modal content has overflow: auto or overflow-y: auto then yes.

mbrowne avatar Jun 05 '18 21:06 mbrowne

Hello. Does anyone know the solution to this issue? I tried all proposed ones and have again the scroll of the background enabled.

triathletefr23-zz avatar Jul 16 '18 16:07 triathletefr23-zz

@triathlet23 I've gone with @AlecRust solution, the other react modal doesn't have this issue.

kaiomagalhaes avatar Jul 16 '18 16:07 kaiomagalhaes

Thanks for a suggestion, but we've built a complete app with the react modal. If smb is interested, I used the solution that was partly proposed in the thread : OnAfterClose={() => document.body.style.overflow = 'hidden' } OnRequestClose={() => document.body.removeAttribute('style') } It woks fine for me and hasn't any side effects.

triathletefr23-zz avatar Jul 17 '18 12:07 triathletefr23-zz

I'll reopen this issue, so it's visible for people looking for help.

diasbruno avatar Jul 17 '18 12:07 diasbruno

@kaiomagalhaes only to use react-aria-modal instead.

react-aria-modal from davidtheclark uses https://github.com/davidtheclark/no-scroll. So you can also implement that into your modal to fix the scroll issue. It basically disables the document scroll behavoir.

WemkoDijkhuis avatar Nov 16 '18 15:11 WemkoDijkhuis

no-scroll helped us to solve this issue. :)

We did something like this:

  useEffect(() => {
    if (open) {
      noScroll.on()
    }

    return () => noScroll.off()
  })

ghost avatar Mar 26 '19 09:03 ghost

shouldFocusAfterRender={false}

works fine for me.

bertho-zero avatar Mar 27 '19 15:03 bertho-zero

shouldFocusAfterRender={false}

works fine for me.

Does it? This did not prevent the page behind the modal from scrolling for me... As far as I can tell it did not change anything. Searching through the react-modal docs for "shouldFocusAfterRender" returned zero results. Where did you find this prop name?

rothwelljeff avatar Apr 04 '19 16:04 rothwelljeff

no-scroll explicitly says that it does not work for iOS in their readme image and references to use the solution at body-scroll-lock, which explains the cons to many of the approaches suggested above in their readme image After trying many of the above suggested solutions, and getting the errors that are stated in the body-scroll-lock readme. I have decided to go with the aforementioned package that solves this clearly-not-one-simple-solution-fits-all problem.

Bartlebyy avatar Apr 08 '19 21:04 Bartlebyy

no-scroll explicitly says that it does not work for iOS in their readme

I've read this too and no-scroll is working for us on iOS.

ghost avatar Apr 09 '19 05:04 ghost