子divをスクロールするとウィンドウがスクロールしますが、どうすれば停止できますか?


回答:


68

次のようにして、ページ全体のスクロールを無効にすることができます。

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

33
良いですが、divの上にカーソルを置くとブラウザーのスクロールバーが消えます。
cstack 2012

@cstackあなたが正しいので、OP(ジーバン)自身の答えの方が良いのです。
Imran Bughio 2014

2
多くのブラウザのスクロールホイールは、ユーザーがマウスを動かすと消えて再表示されるため、上記のコメントは問題ではなくなりました。
Keith Holliday、2015年

ただし、ページがiframeに埋め込まれている場合、このソリューションは機能しません。
ゴータムクリシュナン2015年

5
解決策ではありません。オーバーフローを非表示に設定すると、スクロールバーが非表示になり、外側の要素のすべてのコンテンツが突然再フォーマットされます。また、これは外部要素がbodyであると想定していますが、別のスクロールdivの場合もあります。
robisrob

43

解決策を見つけました。

http://jsbin.com/itajok

これが私が必要としたものです。

そして、これがコードです。

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

jQueryプラグインを使用します。


廃止の通知による更新

jquery-mousewheelから:

三つの引数(追加の以前の動作deltadeltaXおよびdeltaYイベントハンドラには)廃止されて以降のリリースでは削除されます。

次に、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とbreaksにgithubを使用しています。これは、ここでcontent-type blah blah blahがこれが機能するためです:jsbin.com/itajok/207
Michael J. Calkins

どちらのjsbinも、ChromeデバイスエミュレーターやiPhoneでは機能しないようです。これがまだ機能するかどうか誰か知っていますか?
Dirk Boer

2
「ソリューション」はマウスのスクロールイベントでのみ機能し、ページアップ/ダウンや矢印キーでは機能しません。
スコット

ここで「オフ」が必要なのはなぜですか?
ブラッドジョンソン

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と最初にこれを思いついた人は誰でも乾杯します。ところで-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);
      }
    })
  ;
};    

クロムで動作し、他のソリューションよりもはるかに単純です...他の場所での価格を教えてください...

FIDDLE


3
DOMMouseScrollイベントを追加すると、Firefoxで動作します→ jsfiddle.net
chodorowicz/egqy7mbz

これがjqueryに書き込まれていないことに驚いています。主なポイントの1つは、使用しているブラウザーを気にする必要がないことだと思いました。
robisrob

実際にはどちらも廃止されているようです... wheelイベント
robisrob

これにより、MacbookのChromeでスクロールが著しくぎくしゃくします。承認されたソリューションにはこの問題はありません。
danvk

がっかり。これには非常に多くの異なるバージョンがあります。はuiの重要な側面のように見えますが、非常に直感的でない場合、これがデフォルトの動作であることは本当に驚くべきことです。ブラウザーは、内部のスクロールdivがイベントを代わりにウィンドウに適用できる限界にあることを認識できるように装備されているので、それを照会するために使用できるハンドルがないのはなぜですか?
robisrob

8

divでmouseoverイベントを使用して本体のスクロールバーを無効にしてから、mouseoutイベントを使用して再度アクティブ化できますか?

例えば、HTML

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

そして、次のようなJavaScript:

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つ。
2015

+1これは固溶体です。これをスクロール可能なコンテナーにアタッチする場合、この例ではdivにする必要がありますe.currentTarget
Matt

非常にきれいなソリューション。ありがとう
Thinh Bui 2017

Chrome 61.0.3163.100とSafari 11.0では機能しましたが、FireFox 56.0(Mac OS El Capitan)では機能しませんでした
BigJ

これは最高のネイティブソリューションです。ただし、これfalseaddEventListenerデフォルトであるため、を指定する必要はありません。また、比較は簡単な不等式(あるべきである><)、しません>=か、<=
Quolonelの質問2017

6

私があなたの質問を正しく理解した場合、マウスがdiv(サイドバーとしましょう)の上にあるときにメインコンテンツがスクロールしないようにする必要があります。そのため、スクロールイベントがその親にバブリングしないように、サイドバーはメインコンテンツのスクロールコンテナー(ブラウザーウィンドウでした)の子ではない場合があります。

これには、おそらく次の方法でいくつかのマークアップ変更が必要です。

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

それはで働いて参照してください。このサンプルフィドルとしていることを比較し、このサンプルフィドル、サイドバーのわずかに異なるマウス休暇挙動を有します。

ブラウザのメインスクロールバーで特定のdivのみをスクロールすることもご覧ください。


この場合、サイドバーはラッパーdivの外側にあります。だから私は巻物が親に向かって
泡立つ

「このケース」とはあなたのケースを意味しますか?そうでない場合:あなたはまさに正しいです。もしそうなら:あなたのページがdivのスクロールの終わりにスクロールすると、スクロールメッセージはdivの親に向かって泡立つので、あなたのページとdivは兄弟ではなく親と子だと思います。
NGLN 2012

はい、ページは私のdivの親です。つまり、最後に到達すると、ページのスクロールが開始されますが、これは不要です。
Jeevan

divをメインコンテンツの兄弟にすることができない場合、この問題はHTML + CSSだけでは修正できません。これはデフォルトの動作です。
NGLN 2012

1
これは、提供されたすべての回答の中で最も効率的なソリューションだと思います。ページのベースに適切なクリーンマークアップを配置することで、目的の動作を実現するために必要なCSSおよびJSハックがはるかに少なくなります。

6

ここで回答したように、最近のほとんどのブラウザーはoverscroll-behavior: none;CSSプロパティをサポートしているため、スクロールチェーンを防止できます。それだけです、たった1行です!


2
これは2020年の正解になるはずです。私のユースケースでは、最良の解決策はでしたoverscroll-behavior: contain;
ピア

3

これにより、selector要素を入力した場合、ウィンドウのスクロールが無効になります。チャームのように機能します。

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");
        });
};

使用する簡単な方法の1つは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.