스크롤하는 자식 div가 창을 스크롤합니다. 어떻게 중지합니까?


답변:


68

다음과 같이 수행하여 전체 페이지의 스크롤을 비활성화 할 수 있습니다.

<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>

33
좋지만 div 위로 마우스를 가져갈 때마다 브라우저의 스크롤바가 사라집니다.
cstack 2012-08-09

@cstack 당신이 옳습니다. 그래서 OP (Jeevan) 자신의 대답이 더 좋습니다.
이므 란 Bughio

2
이제 사용자가 마우스를 움직이면 많은 브라우저 스크롤 휠이 사라지고 다시 나타납니다. 따라서 위의 설명은 더 이상 문제가되지 않습니다.
Keith Holliday

이 솔루션은 페이지가 iframe에 삽입 된 경우 작동하지 않습니다.
Gautam Krishnan 2015

5
해결책이 아닙니다. 오버플로를 숨김으로 설정하면 갑자기 외부 요소의 모든 내용을 다시 포맷하는 스크롤바가 숨겨집니다. 또한 이것은 외부 요소가 본문이지만 다른 스크롤 div 일 수 있다고 가정합니다.
robisrob

43

해결책을 찾았습니다.

http://jsbin.com/itajok

이것이 내가 필요한 것입니다.

그리고 이것이 코드입니다.

http://jsbin.com/itajok/edit#javascript,html

jQuery 플러그인을 사용합니다.


지원 중단 알림으로 인한 업데이트

에서 JQuery와 - 마우스 휠 :

이벤트 핸들러에 세 개의 인수 ( delta, deltaXdeltaY)를 추가하는 이전 동작 은 이제 더 이상 사용되지 않으며 이후 릴리스에서 제거됩니다.

event.deltaY이제 다음을 사용해야합니다.

var toolbox = $('#toolbox'),
    height = toolbox.height(),
    scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
  var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
  return !blockScrolling;
});

데모


6
귀하의 링크는 js에 github를 사용하고 내용 유형 blah blah 여기에 이것이 작동하기 때문에 중단됩니다. jsbin.com/itajok/207
Michael J. Calkins

두 jsbin은 Chrome 기기 에뮬레이터와 iPhone에서 작동하지 않는 것 같습니다. 이것이 여전히 작동하는지 아는 사람이 있습니까?
Dirk Boer

2
"솔루션"은 페이지 위 / 아래 또는 화살표 키가 아닌 마우스 스크롤 이벤트에 대해서만 작동합니다.
Scott

여기서 "off"가 필요한 이유는 무엇입니까?
Brad Johnson

16

선택한 솔루션은 예술 작품입니다. 플러그인의 가치가 있다고 생각했습니다 ....

$.fn.scrollGuard = function() {
    return this
        .on( 'wheel', function ( e ) {
            var event = e.originalEvent;
            var d = event.wheelDelta || -event.detail;
            this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
            e.preventDefault();
        });
};    

이것은 나에게 지속적인 불편 함이었고이 솔루션은 내가 본 다른 해킹에 비해 너무 깨끗합니다. 그것이 어떻게 작동하고 얼마나 널리 지원되는지에 대해 더 궁금해하지만 Jeevan과 처음에 이것을 생각해 낸 누구에게나 환호합니다. BTW-stackoverflow 답변 편집기가 필요합니다!

최신 정보

DOM을 전혀 조작하지 않고 조건부로만 버블 링을 방지한다는 점에서 이것이 더 낫다고 생각합니다.

$.fn.scrollGuard2 = function() {
  return this
    .on( 'wheel', function ( e ) {
      var $this = $(this);
      if (e.originalEvent.deltaY < 0) {
        /* scrolling up */
        return ($this.scrollTop() > 0);
      } else {
        /* scrolling down */
        return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
      }
    })
  ;
};    

크롬에서 훌륭하게 작동하고 다른 솔루션보다 훨씬 간단합니다 ... 다른 곳에서 어떻게 작동하는지 알려주세요 ...

깡깡이


3
DOMMouseScroll 이벤트를 추가하면 Firefox에서 작동하게됩니다 → jsfiddle.net/chodorowicz/egqy7mbz/1
chodorowicz

이것이 jquery에 기록되지 않은 것에 놀랐습니다. 가장 중요한 점 중 하나는 사용중인 브라우저를 신경 쓰지 않아도된다는 것입니다.
robisrob

실제로 보이는 모두 ... 사용되지 않습니다 같은 wheel이벤트
robisrob

이로 인해 Macbook의 Chrome에서 스크롤이 눈에 띄게 느려집니다. 허용 된 솔루션에는이 문제가 없습니다.
danvk

실망. 이것에는 너무 많은 다른 버전이 있습니다. UI의 중요한 측면처럼 보이며 직관적이지 않을 때 이것이 기본 동작이라는 것은 놀랍습니다. 분명히 브라우저는 내부 스크롤 div가 이벤트를 창에 대신 적용 할 수있는 한계에 있음을 알 수 있도록 준비되어 있는데, 쿼리 할 수있는 핸들이없는 이유는 무엇입니까?
robisrob

8

div에서 mouseover 이벤트를 사용하여 본문 스크롤바를 비활성화 한 다음 mouseout 이벤트를 사용하여 다시 활성화 할 수 있습니까?

예 : HTML

<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
    content
</div>

그런 다음 자바 스크립트는 다음과 같습니다.

var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
    body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
    body.style.overflowY = 'auto';
}

12
document.body대신 사용할 수도 있습니다 .
Ry-

8

Y 축에서이 작업을 수행하는 브라우저 간 방법은 데스크톱 및 모바일에서 작동합니다. OSX 및 iOS에서 테스트되었습니다.

var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var deltaY = event.deltaY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
}, {passive:false});

scrollArea.addEventListener("touchstart", function(event) {
    this.previousClientY = event.touches[0].clientY;
}, {passive:false});

scrollArea.addEventListener("touchmove", function(event) {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var currentClientY = event.touches[0].clientY;
    var deltaY = this.previousClientY - currentClientY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
    this.previousClientY = currentClientY;
}, {passive:false});

이것은 멋지게 작동합니다! 와, 정확히 내가 검색 한 것. 확실히 더 많은 찬성표가 필요합니다.
delato468

이 솔루션은 꽤 잘 작동하지만 약간의 조정이 필요 다음을 변경할 필요 scrollTop === maxScroll 에 의해를 scrollTop >= maxScroll. 1의 경우에, 그것이 필요하다고하여 이상한 것 같다
tchiot.ludo

7

이 문제에 대한 해결책을 썼습니다.

  var div;
  div = document.getElementsByClassName('selector')[0];

  div.addEventListener('mousewheel', function(e) {
    if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
      e.preventDefault();
      div.scrollTop = div.scrollHeight;
    } else if (div.scrollTop + e.deltaY <= 0) {
      e.preventDefault();
      div.scrollTop = 0;
    }
  }, false);

오버플로 숨김 설정으로 인해 페이지 요소가 성가 시게 점프하지 않고 작동하는 몇 가지 솔루션 중 하나입니다.
회의론자

+1 이것은 고체 솔루션입니다. 이것을 스크롤 가능한 컨테이너에 연결하면이 예제에서 div가 e.currentTarget.
매트

매우 깨끗한 솔루션. 감사합니다
틴 부이

Chrome 61.0.3163.100 및 Safari 11.0에서는 작동했지만 FireFox 56.0 (Mac OS El Capitan)에서는 작동하지 않았습니다
BigJ

이것이 최고의 기본 솔루션입니다. 그러나 기본값이기 때문에 false지정할 필요가 없습니다 addEventListener. 또한, 비교는 단순한 불평등 (해야 >하고 <),하지 >=<=.
Quolonel 질문

6

귀하의 질문을 올바르게 이해했다면 마우스가 div 위에있을 때 주요 콘텐츠 스크롤을 방지하고 싶습니다 (사이드 바라고 가정 해 보겠습니다). 이를 위해 사이드 바는 스크롤 이벤트가 부모에게 버블 링되는 것을 방지하기 위해 기본 콘텐츠 (브라우저 창)의 스크롤 컨테이너의 자식이 아닐 수 있습니다.

다음과 같은 방식으로 일부 마크 업 변경이 필요할 수 있습니다.

<div id="wrapper"> 
    <div id="content"> 
    </div> 
</div> 
<div id="sidebar"> 
</div> 

그것에서 일하고 참조하십시오 이 샘플 바이올린 과 비교하여 해당 이 샘플 바이올린 사이드 바의 약간 다른 마우스 휴가 동작이 있습니다.

브라우저의 기본 스크롤바로 특정 div 하나만 스크롤하는 것도 참조하십시오 .


이 경우 사이드 바는 래퍼 div 외부에 있습니다. 그래서 두루마리가 부모에게 버블 링되지 않을 것이라고 생각합니다
Jeevan

"이 사건"이란 당신 사건을 의미합니까? 그렇지 않다면 : 당신이 정확히 옳습니다. 그렇다면 페이지가 div 스크롤이 끝날 때 스크롤되면 스크롤 메시지가 div 부모에게 버블 링되므로 페이지와 div가 형제가 아니라 부모와 자식이라고 생각합니다.
NGLN

예, Page는 내 div의 부모이므로 끝에 도달하면 페이지를 스크롤하기 시작합니다.
Jeevan 2012

div를 기본 콘텐츠의 형제로 만들 수없는 경우 HTML + CSS만으로는이 문제를 해결할 수 없습니다. 기본 동작입니다.
NGLN

1
나는 이것이 제공된 모든 답변 중 가장 효율적인 솔루션이라고 생각합니다. 페이지 하단에 깔끔한 마크 업이 있으면 원하는 동작을 얻기 위해 CSS 및 JS 해킹이 훨씬 적게 필요합니다.

6

여기 에서 대답했듯이 대부분의 최신 브라우저는 이제 overscroll-behavior: none;스크롤 체인을 방지 하는 CSS 속성을 지원합니다 . 그리고 그게 바로 한 줄입니다!


2
이것이 2020 년의 정답이 될 것입니다. 제 사용 사례에 가장 적합한 솔루션은 overscroll-behavior: contain;.
Pier

3

이렇게하면 선택기 요소를 입력하면 창에서 스크롤이 비활성화됩니다. 매력처럼 작동합니다.

elements = $(".selector");

elements.on('mouseenter', function() {
    window.currentScrollTop = $(window).scrollTop();
    window.currentScrollLeft = $(window).scrollTop();
    $(window).on("scroll.prevent", function() {
        $(window).scrollTop(window.currentScrollTop);
        $(window).scrollLeft(window.currentScrollLeft);
    });
});

elements.on('mouseleave', function() {
    $(window).off("scroll.prevent");
});

이것은 실제로 작동하는 솔루션입니다. 순수한 js로 필요했기 때문에 다시 썼습니다. 누구든지 필요하면 여기 있습니다 . 여전히 솔루션을 찾는 사람은 아래의 내 대답을 확인해야 합니다 .
Andriy Stolyar

2

이렇게하면 전체 페이지 스크롤을 비활성화 할 수 있지만 스크롤바는 표시됩니다!

<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>

2
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
  var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
  var scrollTop = this.scrollTop;
  if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
    e.preventDefault();
  }
});

1

ceed의 답변에 따라 스크롤 보호 요소 중첩을 허용하는 버전이 있습니다. 마우스가있는 요소 만 스크롤되며 매우 부드럽게 스크롤됩니다. 이 버전은 재진입도 가능합니다. 동일한 요소에서 여러 번 사용할 수 있으며 핸들러를 올바르게 제거하고 다시 설치합니다.

jQuery.fn.scrollGuard = function() {
    this
        .addClass('scroll-guarding')
        .off('.scrollGuard').on('mouseenter.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g[0].myCst = $g.scrollTop();
            $g[0].myCsl = $g.scrollLeft();
            $g.off("scroll.prevent").on("scroll.prevent", function() {
                $g.scrollTop($g[0].myCst);
                $g.scrollLeft($g[0].myCsl);
            });
        })
        .on('mouseleave.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g.off("scroll.prevent");
        });
};

사용하기 쉬운 한 가지 방법 scroll-guard은 스크롤을 허용하는 페이지의 모든 요소에 와 같은 클래스를 추가하는 것 입니다. 그런 다음 $('.scroll-guard').scrollGuard()그들을 보호 하기 위해 사용하십시오 .


0

overflow: hidden스타일 을 적용하면 사라져야합니다

편집 : 실제로 나는 당신의 질문을 잘못 읽었습니다. 그것은 스크롤 바를 숨길 뿐이지 만 당신이 찾고있는 것이 아니라고 생각합니다.


1
스크롤바가 모두 필요합니다. 행동에 대해 이야기하고 있습니다. div의 스크롤 끝에 도달했을 때 마우스 트랙볼을 사용하여 스크롤 할 때 전체 페이지를 스크롤해서는 안됩니다.
Jeevan

0

Chrome과 Firefox에서 작동하는 데 대한 답을 얻을 수 없었기 때문에 다음과 같은 통합을 생각해 냈습니다.

$someElement.on('mousewheel DOMMouseScroll', scrollProtection);

function scrollProtection(event) {
    var $this = $(this);
    event = event.originalEvent;
    var direction = (event.wheelDelta * -1) || (event.detail);
    if (direction < 0) {
        if ($this.scrollTop() <= 0) {
            return false;
        }
    } else {
        if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
            return false;
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.