Here is the somewhat contrived code:
function h (evt) {
if(evt.target.nodeName !=== 'POPUP') {
evt.preventDefault()
}
}
window.addEventListener('DOMMouseScroll', h, false)
window.addEventListener('wheel', h, false)
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened.
But this doesn't work because evt.target
contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target
will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
https://jsfiddle.net/zr9hjL4s/1/
Seems the trick here is to work altogether with the js dynamic code to stopPropagation and preventDefault behavior of scrolling plus the css code to hide the overflow capability that enables the browser scrolling over elements. So to consider here first, is once the modal is opened You need to disable the scrolling over the whole page (body) in this case, not sure how your page is constructed in real scenario but in this case we have a classical modal opened through js by adding the state kind of modal-open and removing the class once we close the modal. The modal is opened by using the js function openModal. In the example provided, I run this function once the whole js code is executed. So the modal will prompt immediately. Also check that the css rule overflow-y is used inside the modal content to let the "inside" be scroll-able.
Depends on your needs. You can play with the code and adapt with the requirement You have, but this code has saved me several times in the past. :D Hope this helps.
const modalContainer = document.getElementById('modal-container');
const modalContent = document.getElementById('modal-content');
function openModal() {
modalContainer.style.display = 'block';
document.body.classList.add('modal-open');
document.body.addEventListener('scroll', disableScroll);
}
function closeModal() {
modalContainer.style.display = 'none';
document.body.classList.remove('modal-open');
document.body.removeEventListener('scroll', disableScroll);
}
modalContainer.addEventListener('click', (event) => {
if (event.target === modalContainer) {
closeModal();
}
});
// Optional: Close the modal when the Escape key is pressed
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeModal();
}
});
function disableScroll(event) {
event.preventDefault();
event.stopPropagation();
}
openModal()
.modal-container {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
z-index: 9999;
overflow: hidden;
}
.modal-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 80%;
max-height: 80%;
padding: 20px;
background-color: white;
border-radius: 10px;
overflow-y: auto;
}
body.modal-open {
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal Window</title>
</head>
<body>
<!-- Your page content goes here -->
<div>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
</div>
<!-- Modal Container -->
<div id="modal-container" class="modal-container">
<div id="modal-content" class="modal-content">
<!-- Your modal content goes here -->
<h2>Modal Window</h2>
<p>Scroll me!!!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.<br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.<br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.<br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.<br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin euismod purus ut facilisis elementum.</p>
<!-- End of modal content -->
</div>
</div>
<!-- End of page content -->
<div>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.<br/>
What it tries to achieve here is to prevent all other scrolling on the page, except inside popup when popup is opened. But this doesn't work because evt.target contains element currently pointed by mouse rather than one that actually scrolled. So either the whole page would be scrolled or just popup conents, but in both cases evt.target will point to some button inside popup.
But the idea is to get what got actually scrolled now, page body or popup.
</div>
</body>
</html>
https://jsfiddle.net/web20opensource/14zp6btL/1/
Why not use the overflow property of the parents to prevent scrolling?
Check out this approach:
// Store previous overflow styles
const previousParentNodesOverflowStylesMap = new Map();
// Show/hide popup click handlers
document.getElementById("showPopup").addEventListener("click", () => {
document.getElementById("popup").style.display = "block";
disablePopupParentNodesOverflow();
});
document.getElementById("hidePopup").addEventListener("click", () => {
document.getElementById("popup").style.display = "none";
restorePopupParentNodesOverflow();
});
// Parents overflow CSS property management
function disablePopupParentNodesOverflow() {
let parentNode = document.getElementById("popup");
while ((parentNode = parentNode.parentNode)) {
if (parentNode.style) {
const {overflowX, overflowY, overflow} = parentNode.style;
previousParentNodesOverflowStylesMap.set(parentNode, {
overflowX,
overflowY,
overflow
});
parentNode.style.overflow = "hidden";
}
}
}
function restorePopupParentNodesOverflow() {
let parentNode = document.getElementById("popup");
while ((parentNode = parentNode.parentNode)) {
const previousOverflowStyle = previousParentNodesOverflowStylesMap.get(parentNode);
if (previousOverflowStyle !== undefined) {
Object.assign(parentNode.style, previousOverflowStyle);
}
}
previousParentNodesOverflowStylesMap.clear();
}
.popup {
display: none;
overflow-y: auto;
background: lightgreen;
position: absolute;
left: 20px;
top: 40px;
width: 100px;
height: 100px;
}
<!-- Creating show/hide popup system -->
<button id="showPopup">
Show popup
</button>
<button id="hidePopup">
Hide popup
</button>
<!-- Popup -->
<div class="popup" id="popup">
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
</div>
<!-- Rest of page -->
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
<P>lorem ipsum dolor</P>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With