-
Notifications
You must be signed in to change notification settings - Fork 808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't scroll parent component when Modal is opened #191
Comments
@rahulthewall there is an callback called |
@rahulthewall Or in CSS, something like:
Which will prevent overflow-y on the body whilst the modal is open. |
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 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, you can use |
...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 |
@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: |
gee, that was a very bad explanation...sorry.
|
Is there another workaround for this? I would like the parent component not to be scrollable while preserving the page scroll |
nevermind, just need to set |
I'm closing this issue for clean up. Thank you all for the tricks, hope we can publish this on the docs. |
For this to work on iOS .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. |
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 only to use react-aria-modal instead. |
I am also looking for a solution to the position of the parent page scrolling to the top when the modal is opened. |
@wiggitamoo I've gone with @AlecRust solution, the other react modal does't have this issue. |
Thanks @AlecRust, I'll use this modal as well. |
hey tried 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:
and then my disableScroll is defined like this
|
@ wiggitamoo
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:
|
@mbrowne does it solve for when you need to scroll the content of the modal? |
As long as the container holding your modal content has |
Hello. Does anyone know the solution to this issue? I tried all proposed ones and have again the scroll of the background enabled. |
@triathlet23 I've gone with @AlecRust solution, the other react modal doesn't have this issue. |
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 : |
I'll reopen this issue, so it's visible for people looking for help. |
|
We did something like this:
|
shouldFocusAfterRender={false} works fine for me. |
no-scroll explicitly says that it does not work for iOS in their readme |
I've read this too and |
@diasbruno Is there a reason as to why this behavior is not supported internally by react-modal? It seems to me that in most cases you would want to disable scroll when you open a modal, perhaps there should at least be a prop to enable/disable this behaviour. |
This worked for me except I think there's a typo: it should be |
@YassienW Sorry for the delay on this. Yeah, totally agree. Unfortunately, I don't have much time to work on this. So, if anyone has interest, and time, to help this, it would be great. |
Using https://www.npmjs.com/package/no-scroll was the only solution that worked for me... All others had the side effect of "bumping the scroll position to the top of the page" when the modal was rendered |
This example of how you can lock body scroll for mobile and desktop |
Change the overflow to hidden might change the width of the page when the scroll bar is hidden, this causes visual disruption in user visual. |
There are several alternatives to using |
If like me, you spent hours trying to find a scroll solution for Safari 10, I found it and made a simple React hooks version here: https://codesandbox.io/s/react-modal-scrollable-safari-10-friendly-3xzzy |
I used a similar solution:
I left onRequestClose specifically to close the modal or any other action that the page needs. |
In case it helps anyone, using body-scroll-lock could look something like this: import React, { useEffect } from "react";
import ReactModal from "react-modal";
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks,
} from "body-scroll-lock";
export const Modal = ({
isOpen,
children,
onRequestClose,
...props
}) => {
ReactModal.setAppElement("#my-app-element");
let contentEl = null;
useEffect(() => {
return clearAllBodyScrollLocks;
});
return (
<ReactModal
isOpen={isOpen}
onAfterOpen={() => disableBodyScroll(contentEl)}
onRequestClose={() => {
enableBodyScroll(contentEl);
onRequestClose();
}}
contentRef={(element) => (contentEl = element)}
{...props}
>
{children}
</ReactModal>
);
}; Depending on your use case, you could use The const ModalParent = () => {
const [modalOpen, setModalOpen] = useState(false);
return (
<div>
<button onClick={() => setModalOpen(true)}>open modal</button>
<Modal isOpen={modalOpen} onRequestClose={() => setModalOpen(false)}>
Modal content
</Modal>
</div>
);
}; |
To the authors of React Modal: I'd assumed that locking the body scroll was a built-in feature and that was one of the main reasons for using this lib. Is this just a regression or was that never actually included in functionality? Pretty much a must-have in all situations. Thanks! |
I just read the docs and put code result: <Modal
// other attributes
htmlOpenClassName="overflow-hidden"
>
// your html
</Modal> Btw, I used Tailwind for that and you can change the |
Hi, I've also solved this issue by using this hooks : https://gist.github.com/reecelucas/2f510e6b8504008deaaa52732202d2da import Modal from 'react-modal';
....
const [blockScroll, allowScroll] = useScrollBlock();
const ModalParent = () => {
const [modalOpen, setModalOpen] = useState(false);
....
return (
<div>
<button onClick={() => {setModalOpen(true); blockScroll(); }>open modal</button>
<Modal isOpen={modalOpen} onRequestClose={() => {setModalOpen(false); allowScroll();}}>
Modal content
</Modal>
</div>
);
}; |
@maxgfr This is a nice answer. It would be nice if it was in the docs... 😉 |
So if you are using react and have an open state hook this appears to work. I'm still testing though.
|
This issues is terrible, mostly because it doesn't have a good answer. In 6 years, there are a lot of browser versions out there, some of them with this unfortunate behavior (or bug). Best scenario is to add a library to handle this, but I'm not sure if it would cause too much trouble on existing projects. A nice implementation is to provide a simple component that can extend react-modal. const Modal = (props) => {
return (
<ReactModal {...props}
onAfterOpen={() => libToBlockScroll()}
onRequestClose={() => (libToUnblockScroll(), props.onRequestClose())}
>{props.children}</ReactModal>
);
} If anyone want to help with this, with some ideas, I'd appreciate. |
I've added a z-index to the overlay and it prevents the parent from scrolling. Maybe this isn't the solution you were looking for but it works for me in all browsers I've tested so far (I don't know if it works on iOS) |
For those of you who want a solution that doesn't cause the scrollbar to disappear, we are using this solution in our library. export function useFixedBody(isOpen: boolean) {
useEffect(() => {
if (isOpen) {
const x = window.scrollX;
const y = window.scrollY;
const disableScroll = () => {
window.scrollTo(x, y);
};
window.addEventListener('scroll', disableScroll);
return () => {
window.removeEventListener('scroll', disableScroll);
};
}
}, [isOpen]);
} |
This seems like the simplest most straight forward solution. I just wonder if this potentially causes cross compatibility issues |
Although this solution is simple, there are libraries out there that can handle this. It should be preferred because they may have fixes some quirks related to browsers and their versions. |
If the content in the modal is too long there are two scrollbars. So this fix is also not perfect. |
Summary: Don't scroll parent component when Modal is opened
Steps to reproduce:
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?
The text was updated successfully, but these errors were encountered: