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

Opening modal causes body scroll top or bottom

Open prztrz opened this issue 6 years ago • 20 comments

I have an issue that wehever I open the modal the body is immediatelly scrolled to top or to bottom of the website. When the modal is closed the user is not in the place he/she opened the modal but either on the top or on the bottom of website.

I used following CSS to prevent parent element from scrolling (it allways causes the body scrolling top when modal is opened):

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

When I try to use just overflow:hidden as recommended in readme.md it does not work for me - the parent element is still scrollable. When I try to use it without position: fixed as below:

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

It always causes the body scroll bottom when modal is opened.

Skipping width: 100% causes the body content is shifted to the left if position: fixed is used as well.

prztrz avatar Dec 18 '17 22:12 prztrz

Until now I was only seeing the issue in firefox. But as of today, this is happening in on both firefox and chrome.

ryansukale avatar Dec 29 '17 19:12 ryansukale

Wild guess: Could it be that you have something like:

<a href="#" onClick={() => this.openModal()}>Open modal</a>

and forgot event.preventDefault()? (You could also use a <button>.)

<a href="#" onClick={event => {event.preventDefault(); this.openModal()}}>Open modal</a>

Edit: I think this is a duplicate of https://github.com/reactjs/react-modal/issues/117#issuecomment-333409035

lydell avatar Jan 03 '18 12:01 lydell

@lydell unfortunatelly this is not the problem in my case. Clickable elements are <div aria-role="button"> those should not cause automatically reload page by default, however I tried event.preventDefault() anyway and it did not work.

For now I worked the problem around engaging state and additional scrollBack() function like here:

//changing modal isOpen prop to true
//param scrollPos is a number returned by window.scrollY
openModal = scrollPos => { 
    this.setState({
        isModalOpen: true,
        scrollPosOnModalOpen: scrollPos
    })
}

onRequestClose = () => {
    this.setState({
        isModalOpen: false,
   }, this.scrollBack)
}

scrollBack = () => {
     window.scrollTo(0, this.state.scrollPosOnModalOpen)
}

Well it works but does not look very efficient.

prztrz avatar Jan 03 '18 12:01 prztrz

@prztrz @lydell @ryansukale Can you check if #588 can help with this issue?

diasbruno avatar Jan 03 '18 12:01 diasbruno

@diasbruno thank you, this solution solved my problem.

prztrz avatar Jan 03 '18 13:01 prztrz

Please, if you have some time available, go ahead and review the PR. :)

diasbruno avatar Jan 03 '18 13:01 diasbruno

@diasbruno is there any other reason why setting both .ReactModal__Body--open and .ReactModal__Html--open to hide overflow not prevent the scrolling? I confirmed that the classes and styles are added but it still scrolls to top when the modal is open.

woniesong92 avatar Feb 21 '18 14:02 woniesong92

@woniesong92 Can you make a simple example for this case?

[Edit]

I found, in the docs, where I missed to tell about this prop is null by default.

diasbruno avatar Feb 21 '18 14:02 diasbruno

Hey @diasbruno, I tried this property but it seems still scrolling to the top of the page. I copy this code from developer console:

.ReactModal__Body--open, .ReactModal__Html--open {
    overflow: hidden;
}

Can you explain more as @woniesong92's have asked about how this theory works? is there any example of this property?

darrylsepeda avatar May 30 '18 11:05 darrylsepeda

@prztrz what changes you made to resolve your issue, can you mention it here, I am also having the same issue when modal is open the page is scrolled automatically to the bottom of the page. I read about the solution given above but got nothing from it which can work fine for me.

webmastervishal avatar Jul 09 '18 11:07 webmastervishal

+1, I'm still having this issue with v3.5.1. Upon opening the window, the background scrolls all the way to the bottom. Really breaks the UX flow when you close the modal and find yourself at the bottom of the page. I've added the

htmlOpenClassName='ReactModal__Html--open

prop and have set the overflow: hidden's, but this is still occurring.

Kelby2 avatar Jul 16 '18 20:07 Kelby2

@webmastervishal in general adding overflow: hidden to html tag solved the problem.

prztrz avatar Jul 16 '18 21:07 prztrz

@webmastervishal I was able to stop the scrolling to top/bottom on open behavior by adding position: fixed to .ReactModalPortal

CSS:

.ReactModal__Body--open {
  position: static;
  overflow-y: scroll;
}

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

.ReactModalPortal {
  position: fixed;
  z-index: 1 !important;
}

Also remember to pass htmlOpenClassName='ReactModal__Html--open' prop to the Modal.

Kelby2 avatar Jul 19 '18 04:07 Kelby2

@Kelby2 I tried your solution but my problem isn't resolved, My problem is that whenever I redirect to a new page and if modal is opened then it scrolls down automatically to the bottom of the page. check this video.

I don't have a problem if I am able to scroll the background page up and down when modal is open, but whenever I redirect to the new page and modal opens then it must be on the top of the page, instead of scrolling to the bottom of the page.

webmastervishal avatar Jul 25 '18 02:07 webmastervishal

If you use an element that isn't focusable, adding a tabIndex attribute to the element solved the issue for me. When the modal is closed, the page will go back to the element as it will still be focused.

i.e <img onClick={() => this.openModal() tabindex='0'/>

Teranjit avatar Sep 12 '18 07:09 Teranjit

Just adding an outsider perspective. I've dealt with the OP's problem (background jumps to top when opening modal) with vanilla JS modals and the culprit is often the <a href="#"> and how a browser deals with "#".

Consider making your clickable element not <a>, perhaps a button or just a plain div with a listener. In any case, semantically, should an <a> be used for anything other than an actual link?

kalnode avatar Aug 04 '19 02:08 kalnode

Fixed it! Delving into the code...

body.modal-open {position:static !important; overflow:visible; padding:0 !important;}

TheCraftConsulting avatar Aug 09 '19 11:08 TheCraftConsulting

The right answer is by @TheMangoTrain, the "#" value to the <a> element with href attribute is what causes the page to jig, so changing the element to a <button> will resolve the issue! Thanks @TheMangoTrain

jaybabak avatar Sep 17 '19 14:09 jaybabak

@webmastervishal I was able to stop the scrolling to top/bottom on open behavior by adding position: fixed to .ReactModalPortal

CSS:

.ReactModal__Body--open {
  position: static;
  overflow-y: scroll;
}

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

.ReactModalPortal {
  position: fixed;
  z-index: 1 !important;
}

Also remember to pass htmlOpenClassName='ReactModal__Html--open' prop to the Modal.

This works for me but is this the solution or just a walkaround as we wai for the problem to be fixed in the package??

maxwaiyaki avatar May 12 '20 11:05 maxwaiyaki

I have a transition while modal is opening, and during this transition I can still see how the body scrolls to top.

(After three years this is still opened, jeez)

kolnogorov avatar Oct 29 '20 10:10 kolnogorov

Wild guess: Could it be that you have something like:

<a href="#" onClick={() => this.openModal()}>Open modal</a>

and forgot event.preventDefault()? (You could also use a <button>.)

<a href="#" onClick={event => {event.preventDefault(); this.openModal()}}>Open modal</a>

Edit: I think this is a duplicate of #117 (comment)

This works for me, thanks !

esp-tuyen avatar Mar 07 '23 03:03 esp-tuyen

This is not a react-modal bug, it's a browser behavior. Each browser does its own thing, so it's hard to get it right.

There are better packages that helps preventing/normalize this behavior across different browsers.

diasbruno avatar Mar 07 '23 14:03 diasbruno

I'm going to close this one, but please feel free to open a discussion if react-modal should add a package to deal with this, or, users should be free to choose.

diasbruno avatar Mar 07 '23 14:03 diasbruno