web-dev-qa-db-ja.com

モーダルを開いたときにBODYがスクロールしないようにする

私のウェブサイトのモーダル( http://Twitter.github.com/bootstrap から)を開いている間、マウスホイールを使用すると、体がスクロールしなくなります。

モーダルが開かれたときに以下のjavascriptを呼び出そうとしましたが、成功しませんでした

$(window).scroll(function() { return false; });

AND

$(window).live('scroll', function() { return false; });

私達のウェブサイトがIE6のサポートをやめたことに注意してください、しかしIE7 +は互換性がある必要があります。

300
xorinzor

ブートストラップのmodalは、モーダルダイアログが表示されると自動的にクラスにmodal-openをボディに追加し、ダイアログが非表示になるとそれを削除します。したがって、CSSに以下を追加することができます。

body.modal-open {
    overflow: hidden;
}

あなたは上記のコードがBootstrap CSSコードベースに属すると主張するかもしれません、しかしこれはあなたのサイトにそれを追加するための簡単な修正です。

2013年8月8日更新
これはTwitter Boostrap v。2.3.0で機能しなくなりました - 彼らはもはやmodal-openクラスをボディに追加しません。

回避策は、モーダルが表示されようとしているときに本体にクラスを追加し、モーダルが閉じられたときにそれを削除することです。

$("#myModal").on("show", function () {
  $("body").addClass("modal-open");
}).on("hidden", function () {
  $("body").removeClass("modal-open")
});

2013年3月11日の更新 Bootstrap 3.0ではmodal-openクラスがスクロールを防ぐ目的で明示的に返されるように見えます。

体に.modal-openを再導入します(そこでスクロールを無効にできます)。

これを見なさい: https://github.com/Twitter/bootstrap/pull/6342 - モーダル セクションを見なさい。

432
MartinHN

受け入れられた答えはモバイル(少なくともiOS 7 w/Safari 7)では機能せず、CSSが機能するときに私のサイトでMOAR JavaScriptを実行したくない。

このCSSは、背景ページがモーダルの下でスクロールするのを防ぎます。

body.modal-open {
    overflow: hidden;
    position: fixed;
}

しかし、それはまた本質的に一番上にスクロールするというわずかな副作用もあります。 position:absoluteはこれを解決しますが、モバイルでスクロールする機能を再導入します。

あなたのビューポートを知っていれば( ビューポートを<body> に追加するための私のプラグイン)、positionにCSSトグルを追加することができます。

body.modal-open {
    // block scroll for mobile;
    // causes underlying page to jump to top;
    // prevents scrolling on all screens
    overflow: hidden;
    position: fixed;
}
body.viewport-lg {
    // block scroll for desktop;
    // will not jump to top;
    // will not prevent scroll on mobile
    position: absolute; 
}

モーダルの表示/非表示の際に、基礎となるページが左右にジャンプしないようにするためにもこれを追加します。

body {
    // STOP MOVING AROUND!
    overflow-x: hidden;
    overflow-y: scroll !important;
}

この答えはx投稿です。

109
Brad

ボディオーバーフローを隠すだけで、ボディがスクロールしなくなります。モーダルを非表示にしたら、それを自動に戻します。

これがコードです:

$('#adminModal').modal().on('shown', function(){
    $('body').css('overflow', 'hidden');
}).on('hidden', function(){
    $('body').css('overflow', 'auto');
})
28

あなたはオーバーフローでボディサイズをウィンドウサイズに設定することを試みることができました:モーダルが開いているとき隠される

20
charlietfl

警告: 以下のオプションはBootstrap v3.0.xには関係ありません。これらのバージョンでのスクロールはモーダル自体に限定されているためです。ビューポートの高さよりも高い高さを持つモーダルでコンテンツを表示することはできません。


もう一つの選択肢:ホイールイベント

scroll イベントはキャンセルできません。ただし、 マウスホイール および wheel イベントをキャンセルすることは可能です。大きな注意点は、すべてのレガシーブラウザがそれらをサポートしているわけではないということです。Mozillaはつい最近Gecko 17.0で後者のサポートを追加しました。私は本格的な普及を知らないが、IE6 +とChromeはそれらをサポートしている。

これらを活用する方法は次のとおりです。

$('#myModal')
  .on('shown', function () {
    $('body').on('wheel.modal mousewheel.modal', function () {
      return false;
    });
  })
  .on('hidden', function () {
    $('body').off('wheel.modal mousewheel.modal');
  });

JSFiddle

17
merv

@ charlietflの答えを超えてスクロールバーを考慮する必要があります。そうしないと、文書がリフローすることがあります。

モーダルを開く:

  1. bodyの幅を記録する
  2. bodyのオーバーフローをhiddenに設定します
  3. 明示的に本体の幅を手順1の幅に設定します。

    var $body = $(document.body);
    var oldWidth = $body.innerWidth();
    $body.css("overflow", "hidden");
    $body.width(oldWidth);
    

モーダルを閉じる:

  1. bodyのオーバーフローをautoに設定します
  2. bodyの幅をautoに設定します

    var $body = $(document.body);
    $body.css("overflow", "auto");
    $body.width("auto");
    

に触発: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php

14
jpap

これを試してください:

.modal-open {
    overflow: hidden;
    position:fixed;
    width: 100%;
    height: 100%;
}

それは私のために働きました。 (IE 8をサポート)

9
fatCop
/* =============================
 * Disable / Enable Page Scroll
 * when Bootstrap Modals are
 * shown / hidden
 * ============================= */

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}

function theMouseWheel(e) {
  preventDefault(e);
}

function disable_scroll() {
  if (window.addEventListener) {
      window.addEventListener('DOMMouseScroll', theMouseWheel, false);
  }
  window.onmousewheel = document.onmousewheel = theMouseWheel;
}

function enable_scroll() {
    if (window.removeEventListener) {
        window.removeEventListener('DOMMouseScroll', theMouseWheel, false);
    }
    window.onmousewheel = document.onmousewheel = null;  
}

$(function () {
  // disable page scrolling when modal is shown
  $(".modal").on('show', function () { disable_scroll(); });
  // enable page scrolling when modal is hidden
  $(".modal").on('hide', function () { enable_scroll(); });
});
8
jparkerweb

CSSを変更しただけではChrome上で機能させることができませんでした。ページを上にスクロールしたくないからです。これはうまくいきました:

$("#myModal").on("show.bs.modal", function () {
  var top = $("body").scrollTop(); $("body").css('position','fixed').css('overflow','hidden').css('top',-top).css('width','100%').css('height',top+5000);
}).on("hide.bs.modal", function () {
  var top = $("body").position().top; $("body").css('position','relative').css('overflow','auto').css('top',0).scrollTop(-top);
});
7
tetsuo

このコードについてはよくわかりませんが、一撃の価値があります。

JQueryでは:

$(document).ready(function() {
    $(/* Put in your "onModalDisplay" here */)./* whatever */(function() {
        $("#Modal").css("overflow", "hidden");
    });
});

私が前に言ったように、私は100%確実ではありませんがとにかく試してください。

6
Anish Gupta

クラス 'is-modal-open'を追加したり、javascriptでbodyタグのスタイルを変更したりしても問題ありません。しかし、私たちが直面する問題は、本体がオーバーフローしたときです。これは後で使い勝手の問題になるでしょう。

この問題の解決策として、bodyタグのオーバーフローを変更するのではなく、隠しhtmlタグで変更します。

$('#myModal').on('shown.bs.modal', function () {
  $('html').css('overflow','hidden');
}).on('hidden.bs.modal', function() {
  $('html').css('overflow','auto');
});

Bootstrap の場合は、これを試すことができます(FirefoxChrome、およびMicrosoft Edgeに取り組んでいます)。

body.modal-open {
    overflow: hidden;
    position:fixed;
    width: 100%;
}

お役に立てれば...

5
Murat Yıldız

最善の解決策は、これらの回答のほとんどで使用されているCSS専用のbody{overflow:hidden}解決策です。一部の回答では、スクロールバーが消えることによって引き起こされる「ジャンプ」を防ぐ修正も提供されています。しかし、どれもエレガントすぎませんでした。だから、私はこれら二つの関数を書いた、そしてそれらはかなりうまくいくように思われる。

var $body = $(window.document.body);

function bodyFreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('overflow', 'hidden');
    $body.css('marginRight', ($body.css('marginRight') ? '+=' : '') + ($body.innerWidth() - bodyWidth))
}

function bodyUnfreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('marginRight', '-=' + (bodyWidth - $body.innerWidth()))
    $body.css('overflow', 'auto');
}

this jsFiddle をチェックしてください。

3

あなたは次のロジックを使うことができます、私はそれをテストしました、そしてそれは(IEの中でさえ)働きます

   <html>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">

var currentScroll=0;
function lockscroll(){
    $(window).scrollTop(currentScroll);
}


$(function(){

        $('#locker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).bind('scroll',lockscroll);

        })  


        $('#unlocker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).unbind('scroll');

        })
})

</script>

<div>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button id="locker">lock</button>
<button id="unlocker">unlock</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

</div>
3
myriacl

チェックボックスハックによって生成されたサイドバーがありました。しかし主な考え方は、文書scrollTopを保存し、ウィンドウのスクロール中に変更しないことです。

私はただ、bodyが 'overflow:hidden'になったときにページがジャンプするのを好まなかった。

window.addEventListener('load', function() {
    let prevScrollTop = 0;
    let isSidebarVisible = false;

    document.getElementById('f-overlay-chkbx').addEventListener('change', (event) => {
        
        prevScrollTop = window.pageYOffset || document.documentElement.scrollTop;
        isSidebarVisible = event.target.checked;

        window.addEventListener('scroll', (event) => {
            if (isSidebarVisible) {
                window.scrollTo(0, prevScrollTop);
            }
        });
    })

});

悲しいことに、上記の答えのどれも私の問題を直しませんでした。

私の状況では、Webページにもともとスクロールバーがあります。モーダルをクリックするたびに、スクロールバーは消えず、ヘッダーは少し右に移動します。

それから私は.modal-open{overflow:auto;}を追加しようとしました(ほとんどの人がこれをお勧めします)。それは確かに問題を解決した:私はモーダルを開いた後にスクロールバーが表示されます。しかし、もう1つの副作用が出てきます。「ヘッダーの下の背景は、モーダルの後ろの別の長いバーと一緒に、少し左に移動します」ということです。

Long bar behind modal

幸いなことに、{padding-right: 0 !important;}を追加した後、すべてが完全に修正されました。ヘッダとボディの両方の背景は動かず、モーダルはまだスクロールバーを保持します。

Fixed image

これがまだこの問題に立ち往生している人々を助けることを願っています。がんばろう!

2
Bocard Wang

2017年11月現在、Chromeに新しいcssプロパティが導入されました

overscroll-behavior: contain;

執筆時点ではクロスブラウザのサポートが制限されていますが、これはこの問題を解決します。

詳細およびブラウザサポートについては、下記のリンクを参照してください。

2
user1095118

多くの人が "オーバーフロー:隠し"をボディに提案していますが、これはうまくいきません(少なくとも私の場合はそうではありません)。

これは、jQueryを使用して(携帯電話とコンピューターの両方で)私にとって有効な解決策です。

    $('.yourModalDiv').bind('mouseenter touchstart', function(e) {
        var current = $(window).scrollTop();
        $(window).scroll(function(event) {
            $(window).scrollTop(current);
        });
    });
    $('.yourModalDiv').bind('mouseleave touchend', function(e) {
        $(window).off('scroll');
    });

これにより、モーダルのスクロールが機能し、Webサイトが同時にスクロールするのを防ぎます。

2
Danie

このフィドルに基づく: http://jsfiddle.net/dh834zgw/1/ /

次のスニペット(jqueryを使用)はウィンドウスクロールを無効にします。

 var curScrollTop = $(window).scrollTop();
 $('html').toggleClass('noscroll').css('top', '-' + curScrollTop + 'px');

そしてあなたのCSSでは:

html.noscroll{
    position: fixed;
    width: 100%;
    top:0;
    left: 0;
    height: 100%;
    overflow-y: scroll !important;
    z-index: 10;
 }

モーダルを削除するときは、htmlタグのnoscrollクラスを削除することを忘れないでください。

$('html').toggleClass('noscroll');
2
ling

モーダルが100%の高さ/幅の場合、 "mouseenter/leave"はスクロールを簡単に有効/無効にするように働きます。これは私にとって本当にうまくいきました:

var currentScroll=0;
function lockscroll(){
    $(window).scrollTop(currentScroll);
} 
$("#myModal").mouseenter(function(){
    currentScroll=$(window).scrollTop();
    $(window).bind('scroll',lockscroll); 
}).mouseleave(function(){
    currentScroll=$(window).scrollTop();
    $(window).unbind('scroll',lockscroll); 
});
1
Mats

Bootstrap 3のための私の解決策:

.modal {
  overflow-y: hidden;
}
body.modal-open {
  margin-right: 0;
}

私にとってoverflow: hiddenクラスの唯一のbody.modal-openは、元のmargin-right: 15pxのためにページが左に移動するのを妨げませんでした。

1
pierrea

ほとんどの作品はここにありますが、すべてをまとめた答えはありません。

問題は3つあります。

(1)基礎ページのスクロールを防止する

$('body').css('overflow', 'hidden')

(2)スクロールバーを外します

var handler = function (e) { e.preventDefault() }
$('.modal').bind('mousewheel touchmove', handler)

(3)モーダルが解任されたときに片付ける

$('.modal').unbind('mousewheel touchmove', handler)
$('body').css('overflow', '')

モーダルがフルスクリーンではない場合は、.modalバインディングをフルスクリーンオーバーレイに適用します。

1
evoskuil

これがBootstrapでうまくいくかどうかは100%確信できませんが、試してみる価値があります - githubにあるRemodal.jsでうまくいきました: http://vodkabears.github.io/remodal/ メソッドがかなり似ていることには意味があります。

ページの先頭へのジャンプを止め、コンテンツの右への移動を防ぐには、モーダルが起動されたときにクラスをbodyに追加し、次のCSSルールを設定します。

body.with-modal {
    position: static;
    height: auto;
    overflow-y: hidden;
}

position:staticheight:autoが組み合わさってコンテンツの右側へのジャンプを止めます。 overflow-y:hidden;は、ページがモーダルの後ろにスクロール可能になるのを防ぎます。

1
AdamJB

私はちょうどそれをこうやった….

$('body').css('overflow', 'hidden');

しかしスクローラが消えたときそれはすべて正しい20pxを動かした、それで私は加えた

$('body').css('margin-right', '20px');

その直後.

私のために働きます。

1
Cliff

私のために働いた

$('#myModal').on({'mousewheel': function(e) 
    {
    if (e.target.id == 'el') return;
    e.preventDefault();
    e.stopPropagation();
   }
});
1
namal

オーバーフローを隠して位置を固定することはトリックを行いますが、私の流動的な設計ではブラウザの幅を超えてそれを固定するので、幅:100%はそれを修正しました。

body.modal-open{overflow:hidden;position:fixed;width:100%}
0
asked_io

このVanillaのjs関数を使って、 "modal-open"クラスを本体に追加しています。 (smhmicの回答に基づく)

function freezeScroll(show, new_width)
{
    var innerWidth = window.innerWidth,
        clientWidth = document.documentElement.clientWidth,
        new_margin = ((show) ? (new_width + innerWidth - clientWidth) : new_width) + "px";

    document.body.style.marginRight = new_margin;
    document.body.className = (show) ? "modal-open" : "";
};
0
Omer M.

これは私にとって最良の解決策です。

Css:

.modal {
     overflow-y: auto !important;
}

そしてJs:

modalShown = function () {
    $('body').css('overflow', 'hidden');
},

modalHidden = function () {
    $('body').css('overflow', 'auto');
}
0
ibrahimyilmaz

body-scroll-lock を使用

とても軽く、とてもきれいで人気がある

0
adardesign

このコードを試してください:

$('.entry_details').dialog({
    width:800,
    height:500,
    draggable: true,
    title: entry.short_description,
    closeText: "Zamknij",
    open: function(){
        //    blokowanie scrolla dla body
        var body_scroll = $(window).scrollTop();
        $(window).on('scroll', function(){
            $(document).scrollTop(body_scroll);
        });
    },
    close: function(){
        $(window).off('scroll');
    }
}); 
0
   $('.modal').on('shown.bs.modal', function (e) {
      $('body').css('overflow-y', 'hidden');
   });
   $('.modal').on('hidden.bs.modal', function (e) {
      $('body').css('overflow-y', '');
   });
0

SharePoint 2013のユーザー向けの小さなメモです。本文には既にoverflow: hiddenがあります。あなたが探しているのは、id overflow: hiddenを持つdiv要素にs4-workspaceを設定することです。

var body = document.getElementById('s4-workspace');
body.className = body.className+" modal-open";
0
Kristian

他のモーダル内でモーダルを使用すると、上記が発生します。別のモーダルの内側でモーダルを開くと、後者を閉じるとbodyからクラスmodal-openが削除されます。問題の修正は、後者のモーダルをどのように閉じるかによって異なります。

Htmlのようにモーダルを閉じると、

<button type="button" class="btn" data-dismiss="modal">Close</button>

それならこのようなリスナーを追加しなければなりません、

$(modalSelector).on("hidden.bs.modal", function (event) {
    event.stopPropagation();
    $("body").addClass("modal-open");
    return false;
});

Javascriptを使ってモーダルを閉じると、

$(modalSelector).modal("hide");

その後、このようにしてしばらくしてからコマンドを実行する必要があります。

setInterval(function(){$("body").addClass("modal-open");}, 300);
0

ブートストラップ3モーダルのscrollイベントを取得する方法について疑問に思っている人のために:

$(".modal").scroll(function() {
    console.log("scrolling!);
});
0
Arie

私のために最後にこれを直したのは 本体スクロールロック でした。

他の解決策はiOSのスクロールを無効にしません。

0

これは私のために働いた:

$("#mymodal").mouseenter(function(){
   $("body").css("overflow", "hidden"); 
}).mouseleave(function(){
   $("body").css("overflow", "visible");
});
0

クロスプラットフォームでのパフォーマンスを向上させるには、HTMLにoverflow: hiddenを追加してください。

私は使うだろう

html.no-scroll {
    overflow: hidden;
}
0
Afonso

私にとっては、この問題は主にiOSで発生していたので、それを修正するためのコードをiOSでのみ提供します。

  if(!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) {
    var $modalRep    = $('#modal-id'),
        startScrollY = null, 
        moveDiv;  

    $modalRep.on('touchmove', function(ev) {
      ev.preventDefault();
      moveDiv = startScrollY - ev.touches[0].clientY;
      startScrollY = ev.touches[0].clientY;
      var el = $(ev.target).parents('#div-that-scrolls');
      // #div-that-scrolls is a child of #modal-id
      el.scrollTop(el.scrollTop() + moveDiv);
    });

    $modalRep.on('touchstart', function(ev) {
      startScrollY = ev.touches[0].clientY;
    });
  }
0
LowFieldTheory

Bulmaのようにそれをしないのはなぜですか?モーダルがアクティブなときは、HTMLにそれらのクラスを追加します。以上です。

編集:オーケー、ブルマはこのバグを抱えているので、他のものも追加しなければならない

html.is-modal-active {
  overflow: hidden !important;
  position: fixed;
  width: 100%; 
}
0
nrkz