Как запретить прокрутку родительского блока при открытии дочернего?
Поправьте, пожалуйста, как при открытии окна дать возможность его прокручивать, при этом запретить прокрутку блока .container как колесиком мыши, так и зажатой левой клавишей мыши? Благодарю!
// Крутим колесиком мыши
(function() {
function scrollHorizontally(e) {
var scrollPos = this.scrollLeft;
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
this.scrollLeft -= (delta*40);
var widthElem = this.scrollWidth;
var widthBrowser = document.documentElement.clientWidth;
if ((delta == 1 ) && (this.scrollLeft == 0)) return;
if ((widthBrowser >= widthElem) || (scrollPos == this.scrollLeft)) return;
e.preventDefault();
}
var elems = document.querySelectorAll('.container');
for (var a = 0; a < elems.length; a++) {
elems[a].addEventListener("mousewheel", scrollHorizontally, false);
elems[a].addEventListener("DOMMouseScroll", scrollHorizontally, false);
}
})();
// Крутим зажатой левой клавишей мыши
const slider = document.querySelector('.container');
let pressed = false,
startX,
scrollLeft;
slider.addEventListener('mousedown', e => {
pressed = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
document.documentElement.addEventListener('mouseleave', ()=>{
pressed = false;
});
document.documentElement.addEventListener('mouseup', ()=>{
pressed = false;
});
document.documentElement.addEventListener('mousemove', e => {
if( !pressed ) return;
e.preventDefault();
let x = e.pageX - slider.offsetLeft;
slider.scrollLeft = scrollLeft - x + startX;
});
// Открываем окно
$(document).ready(function() {
$('.open_modal').click(function(event) {
event.preventDefault();
let modal = $(this).attr('href'),
overlay = $(modal).closest('.modal_overlay');
overlay.fadeIn(400,
function() {
$('.container').css('overflow-x', 'hidden');
$('body').css('overflow-y', 'hidden');
overlay.css('overflow-y', 'scroll');
if (overlay.innerHeight() > $(modal).outerHeight()) {
$(modal).css("margin-top", (overlay.innerHeight() / 2 - $(modal).outerHeight() / 2) + "px");
}
$(modal)
.css('display', 'block')
.animate({
opacity: 1,
top: '0'
}, 200);
});
});
$('.modal_close').click(function(e) {
$(e.target).closest('.modal_overlay').find('.modal_div')
.animate({
opacity: 0,
top: '0'
}, 200,
function() {
$(this).css('display', 'none');
$(e.target).closest('.modal_overlay').fadeOut(400);
$(e.target).closest('.modal_overlay').css('overflow-y', 'hidden');
$('body').css('overflow-y', 'auto');
$('.container').css('overflow-x', 'auto');
}
);
});
});
* {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
}
.container {
background-color: #f1f1f1;
border: 2px solid black;
width: 100%;
height: 90vh;
overflow-y: hidden;
overflow-x: auto;
white-space: nowrap;
font-smoothing: antialiased;
user-select: none;
cursor: grab;
}
.container:active {cursor: grabbing;}
.item {
display: inline-block;
background-color: gray;
width: 100%;
height: 100%;
vertical-align: top;
margin: 0 5vw;
}
/*Окно*/
.modal_overlay {
display: none;
z-index: 999;
position: fixed;
width: 100%;
height: 100vh;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.8);
}
.modal_div {
display: none;
z-index: 1000;
width: 200px;
margin: 0 auto;
background-color: white;
}
.modal_close {
position: fixed;
top: 10px;
left: 10px;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item"><a href="#modal_1" class="open_modal">Открыть окно</a></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<!-- Окно -->
<div class="modal_overlay">
<div class="modal_close">Закрыть</div>
<div id="modal_1" class="modal_div">
<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1
</div>
</div>
<!-- .Окно -->
</div>
Ответы (4 шт):
Ты специально создал участок кода который двигает .container при зажатой клавише, тебе нужно его полностью убрать, а для прокрутки модального окна тебе нужно было поменять в скрипте класс с которым ты работаешь, у тебя получится вот такой скрипт
(function() {
function scrollHorizontally(e) {
var scrollPos = this.scrollLeft;
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
this.scrollLeft -= (delta*40);
var widthElem = this.scrollWidth;
var widthBrowser = document.documentElement.clientWidth;
if ((delta == 1 ) && (this.scrollLeft == 0)) return;
if ((widthBrowser >= widthElem) || (scrollPos == this.scrollLeft)) return;
e.preventDefault();
}
var elems = document.querySelectorAll('.modal_overlay');
for (var a = 0; a < elems.length; a++) {
elems[a].addEventListener("mousewheel", scrollHorizontally, false);
elems[a].addEventListener("DOMMouseScroll", scrollHorizontally, false);
}
})();
// Открываем окно
$(document).ready(function() {
$('.open_modal').click(function(event) {
event.preventDefault();
let modal = $(this).attr('href'),
overlay = $(modal).closest('.modal_overlay');
overlay.fadeIn(400,
function() {
$('.container').css('overflow-x', 'hidden');
$('body').css('overflow-y', 'hidden');
overlay.css('overflow-y', 'scroll');
if (overlay.innerHeight() > $(modal).outerHeight()) {
$(modal).css("margin-top", (overlay.innerHeight() / 2 - $(modal).outerHeight() / 2) + "px");
}
$(modal)
.css('display', 'block')
.animate({
opacity: 1,
top: '0'
}, 200);
});
});
$('.modal_close').click(function(e) {
$(e.target).closest('.modal_overlay').find('.modal_div')
.animate({
opacity: 0,
top: '0'
}, 200,
function() {
$(this).css('display', 'none');
$(e.target).closest('.modal_overlay').fadeOut(400);
$(e.target).closest('.modal_overlay').css('overflow-y', 'hidden');
$('body').css('overflow-y', 'auto');
$('.container').css('overflow-x', 'auto');
}
);
});
});
Так же я бы советовал писать JS по стандарту ES6, он будет выглядеть гораздо красивее и читабильнее
Нашел простое решение.
- Отменяем действия события по умолчанию при прокрутке колесиком мыши
- Для нужного блока прокрутку делаем с помощью scrollTop
Проверено, работает отлично, прокрутка работает колесиком мышки и зажатием кнопки. Родительский scroll не прокручивается.
Код на Jquery:
$(document).ready(function () {
$('.container').on('mousewheel wheel', function(e) {
let mousewheel = e.originalEvent.deltaY;
$(this).animate({scrollTop:"+=" + mousewheel}, 100, 'linear');
e.preventDefault();
return false;
});
})
body {height:2000px;}
.container {width:200px; height:300px; overflow-x: auto}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="container" >
<h4>Scroll Container</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In luctus,
ex eu sagittis faucibus, ligula ipsum sagittis magna, et imperdiet
dolor lectus eu libero. Vestibulum venenatis eget turpis sed
faucibus. Maecenas in ullamcorper orci, eu ullamcorper sem. Etiam
elit ante, luctus non ante sit amet, sodales vulputate odio. Aenean
tristique nisl tellus, sit amet fringilla nisl volutpat cursus.
Quisque dignissim lectus ac nunc consectetur mattis. Proin vel
hendrerit ipsum, et lobortis dolor. Vestibulum convallis, nibh et
tincidunt tristique, nisl risus facilisis lectus, ut interdum orci
nisl ac nunc. Cras et aliquam felis. Quisque vel ipsum at elit
sodales posuere eget non est. Fusce convallis vestibulum dolor non
volutpat. Vivamus vestibulum quam ut ultricies pretium.
</p>
<p>
Suspendisse rhoncus fringilla nisl. Mauris eget lorem ac urna
consectetur convallis non vel mi. Donec libero dolor, volutpat ut
urna sit amet, aliquet molestie purus. Phasellus faucibus, leo vel
scelerisque lobortis, ipsum leo sollicitudin metus, eget sagittis
ante orci eu ipsum. Nulla ac mauris eu risus sagittis scelerisque
iaculis bibendum mauris. Cras ut egestas orci. Cras odio risus,
sagittis ut nunc vitae, aliquam consectetur purus. Vivamus ornare
nunc vel tellus facilisis, quis dictum elit tincidunt. Donec
accumsan nisi at laoreet sodales. Cras at ullamcorper massa.
Maecenas at facilisis ex. Nam mollis dignissim purus id efficitur.
</p>
</section>
Решение на чистом HTML + CSS
body {height:2000px;}
* {overscroll-behavior: contain; -ms-scroll-chaining: none}
.block {width:500px; height:500px;
background-color: #FFCC99; overflow-y:hidden; overflow-x:scroll;
box-sizing0: content-box;}
.block2 {height:100%; width:calc(100% + 1px);}
.content {margin:50px; height:200px; width:400px; overflow:auto;
background-color: #6699CC;}
/* Chrome, Safari and Opera */
.no_scroll::-webkit-scrollbar { width: 0; background: transparent;}
/* IE and Edge, Firefox */
.no_scroll {-ms-overflow-style: none; scrollbar-width: none; }
<section class="block no_scroll" >
<aside class="block2">
<h3>Родитель без видимого скролла</h3>
<div class="content">
<p style="height:600px;">Элемент со скролом</p>
</div>
</aside>
</section>
Основная проблема у данного метода заключалась в том, что он работает только с элементами у которых есть видимый скролл. В примере я показал, как решить эту проблему - достаточно добавить родителю горизонтальный скролл и визуально срыть его.
На 2022 год Свойство overscroll-behavior не поддерживается OS Safari дискуссии по внедрению ведутся https://bugs.webkit.org/show_bug.cgi?id=176454
Это решение заключается в том чтобы добавить выход из обработчиков при условии если модалка видна:
if ($('.modal_div').css('display') === 'block') return
// Крутим колесиком мыши
(function() {
function scrollHorizontally(e) {
if ( $('.modal_div').css('display') === 'block') return
var scrollPos = this.scrollLeft;
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
this.scrollLeft -= (delta*40);
var widthElem = this.scrollWidth;
var widthBrowser = document.documentElement.clientWidth;
if ((delta == 1 ) && (this.scrollLeft == 0)) return;
if ((widthBrowser >= widthElem) || (scrollPos == this.scrollLeft)) return;
e.preventDefault();
}
var elems = document.querySelectorAll('.container');
for (var a = 0; a < elems.length; a++) {
elems[a].addEventListener("mousewheel", scrollHorizontally, false);
elems[a].addEventListener("DOMMouseScroll", scrollHorizontally, false);
}
})();
// Крутим зажатой левой клавишей мыши
const slider = document.querySelector('.container');
let pressed = false,
startX,
scrollLeft;
slider.addEventListener('mousedown', e => {
pressed = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
document.documentElement.addEventListener('mouseleave', ()=>{
pressed = false;
});
document.documentElement.addEventListener('mouseup', ()=>{
pressed = false;
});
document.documentElement.addEventListener('mousemove', e => {
if ($('.modal_div').css('display') === 'block') return
if( !pressed ) return;
e.preventDefault();
let x = e.pageX - slider.offsetLeft;
slider.scrollLeft = scrollLeft - x + startX;
});
// Открываем окно
$(document).ready(function() {
$('.open_modal').click(function(event) {
event.preventDefault();
let modal = $(this).attr('href'),
overlay = $(modal).closest('.modal_overlay');
overlay.fadeIn(400,
function() {
$('.container').css('overflow-x', 'hidden');
$('body').css('overflow-y', 'hidden');
overlay.css('overflow-y', 'scroll');
if (overlay.innerHeight() > $(modal).outerHeight()) {
$(modal).css("margin-top", (overlay.innerHeight() / 2 - $(modal).outerHeight() / 2) + "px");
}
$(modal)
.css('display', 'block')
.animate({
opacity: 1,
top: '0'
}, 200);
});
});
$('.modal_close').click(function(e) {
$(e.target).closest('.modal_overlay').find('.modal_div')
.animate({
opacity: 0,
top: '0'
}, 200,
function() {
$(this).css('display', 'none');
$(e.target).closest('.modal_overlay').fadeOut(400);
$(e.target).closest('.modal_overlay').css('overflow-y', 'hidden');
$('body').css('overflow-y', 'auto');
$('.container').css('overflow-x', 'auto');
}
);
});
});
* {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
}
.container {
background-color: #f1f1f1;
border: 2px solid black;
width: 100%;
height: 90vh;
overflow-y: hidden;
overflow-x: auto;
white-space: nowrap;
font-smoothing: antialiased;
user-select: none;
cursor: grab;
}
.container:active {cursor: grabbing;}
.item {
display: inline-block;
background-color: gray;
width: 100%;
height: 100%;
vertical-align: top;
margin: 0 5vw;
}
/*Окно*/
.modal_overlay {
display: none;
z-index: 999;
position: fixed;
width: 100%;
height: 100vh;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.8);
}
.modal_div {
display: none;
z-index: 1000;
width: 200px;
margin: 0 auto;
background-color: white;
}
.modal_close {
position: fixed;
top: 10px;
left: 10px;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item"><a href="#modal_1" class="open_modal">Открыть окно</a></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<!-- Окно -->
<div class="modal_overlay">
<div class="modal_close">Закрыть</div>
<div id="modal_1" class="modal_div">
<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1<br>1
</div>
</div>
<!-- .Окно -->
</div>