Impede que o BODY desloque quando um modal é aberto

Eu quero que meu corpo pare de rolar quando usando o mousewheel enquanto o Modal (de http://twitter.github.com/bootstrap ) no meu site é aberto.

Eu tentei chamar o pedaço de javascript abaixo quando o modal está aberto, mas sem sucesso

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

Por favor, note nosso site caiu suporte para o IE6, IE7 + precisa ser compatível embora.

O modal do Bootstrap adiciona automaticamente a class modal-open ao corpo quando um modal dialog é mostrado e o remove quando o diálogo está oculto. Você pode, portanto, adicionar o seguinte ao seu CSS:

 body.modal-open { overflow: hidden; } 

Você poderia argumentar que o código acima pertence à base de código CSS do Bootstrap, mas essa é uma correção fácil para adicioná-lo ao seu site.

Atualização 8 de fevereiro de 2013
Isso parou de funcionar no Twitter Boostrap v. 2.3.0 – eles não adicionam mais a class modal-open ao corpo.

Uma solução alternativa seria adicionar a class ao corpo quando o modal está prestes a ser mostrado e removê-lo quando o modal é fechado:

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

Atualização 11 de março de 2013 Parece que a class modal-open retornará no Bootstrap 3.0, explicitamente com a finalidade de evitar a rolagem:

Reintroduz .modal-aberto no corpo (para que possamos nuke o pergaminho lá)

Veja isto: https://github.com/twitter/bootstrap/pull/6342 – veja a seção Modal .

A resposta aceita não funciona em dispositivos móveis (iOS 7 com Safari 7, pelo menos) e não quero que o MOAR JavaScript seja executado em meu site quando o CSS funcionar.

Este CSS impedirá que a página de plano de fundo se desloque sob o modal:

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

No entanto, também tem um ligeiro efeito lateral de essencialmente rolar para o topo. position:absolute resolve isso, mas reintroduz a capacidade de rolar no celular.

Se você conhece a sua viewport ( meu plugin para adicionar viewport ao ), você pode simplesmente adicionar uma alternância css para a position .

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

Eu também adiciono isso para evitar que a página subjacente salte para a esquerda / direita ao mostrar / ocultar os modais.

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

esta resposta é um x-post.

Simplesmente esconda o excesso de corpo e faz com que o corpo não role. Quando você oculta o modal, reverta para automático.

Aqui está o código:

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

Você pode tentar definir o tamanho do corpo para o tamanho da janela com estouro: oculto quando o modal está aberto

Aviso: A opção abaixo não é relevante para o Bootstrap v3.0.x, já que a rolagem nessas versões foi explicitamente confinada ao próprio modal. Se você desativar os events de roda, poderá inadvertidamente impedir que alguns usuários visualizem o conteúdo em modais que tenham alturas maiores que a altura da janela de visualização.


Ainda outra opção: events de roda

O evento de rolagem não é cancelável. No entanto, é possível cancelar os events roda do mouse e roda . A grande ressalva é que nem todos os navegadores legados os suportam, a Mozilla apenas recentemente adicionou suporte para o último no Gecko 17.0. Não conheço o spread completo, mas o IE6 + e o Chrome os suportam.

Veja como aproveitá-los:

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

JSFiddle

Você precisa ir além da resposta do @ charlietfl e considerar as barras de rolagem, caso contrário você poderá ver um restream do documento.

Abrindo o modal:

  1. Registre a largura do body
  2. Definir excesso de body para hidden
  3. Defina explicitamente a largura do corpo para o que era na etapa 1.

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

Fechando o modal:

  1. Definir excesso de body para auto
  2. Definir body largura do body para auto

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

Inspirado por: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php

 /* ============================= * 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(); }); }); 

Tente este:

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

funcionou para mim. (suporta o IE8)

Não tenho certeza sobre esse código, mas vale a pena tentar.

Em jQuery:

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

Como eu disse antes, não tenho 100% de certeza, mas tente assim mesmo.

Não foi possível fazer isso funcionar no Chrome apenas alterando o CSS, porque não queria que a página rolasse de volta ao topo. Isso funcionou bem:

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

Adicionar a class ‘is-modal-open’ ou modificar o estilo da tag body com javascript está correto e funcionará como deveria. Mas o problema que vamos enfrentar é quando o corpo se torna transbordante: escondido, ele vai saltar para o topo, (scrollTop vai se tornar 0). Isso se tornará um problema de usabilidade mais tarde.

Como uma solução para esse problema, em vez de alterar o estouro da tag de corpo: oculto, altere-o na tag html

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

Você poderia usar a seguinte lógica, eu testei e funciona (mesmo no IE)

     
































































A melhor solução é a solução body{overflow:hidden} somente para css usada pela maioria dessas respostas. Algumas respostas fornecem uma correção que também impede o “salto” causado pela barra de rolagem que está desaparecendo; no entanto, nenhum era elegante demais. Então, eu escrevi essas duas funções e elas parecem funcionar muito bem.

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

Confira este jsFiddle para vê-lo em uso.

Baseado neste violino: http://jsfiddle.net/dh834zgw/1/

o trecho a seguir (usando jquery) desativará a rolagem da janela:

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

E no seu css:

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

Agora, quando você remover o modal, não se esqueça de remover a class noscroll na tag html:

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

Infelizmente, nenhuma das respostas acima corrigiu meus problemas.

Na minha situação, a página da web originalmente tem uma barra de rolagem. Sempre que clico no modal, a barra de rolagem não desaparece e o header se move para a direita um pouco.

Então eu tentei adicionar .modal-open{overflow:auto;} (que a maioria das pessoas recomendou). Isso realmente corrigiu os problemas: a barra de rolagem aparece depois que eu abro o modal. No entanto, outro efeito colateral sai, que é que “o fundo abaixo do header se moverá um pouco para a esquerda, junto com outra barra longa atrás do modal”

Barra longa atrás do modal

Felizmente, depois de adicionar {padding-right: 0 !important;} , tudo foi corrigido com perfeição. Tanto o header quanto o fundo do corpo não se moveram e o modal ainda mantém a barra de rolagem.

Imagem fixa

Espero que isso possa ajudar aqueles que ainda estão presos a esse problema. Boa sorte!

Muitos sugerem “estouro: oculto” no corpo, o que não vai funcionar (não no meu caso, pelo menos), uma vez que fará o site rolar para o topo.

Essa é a solução que funciona para mim (tanto em celulares quanto em computadores), usando 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'); }); 

Isso fará com que a rolagem do modal funcione e impedirá que o site seja rolado ao mesmo tempo.

A maioria das peças está aqui, mas não vejo nenhuma resposta que junte tudo.

O problema é triplo.

(1) impedir o deslocamento da página subjacente

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

(2) e remova a barra de rolagem

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

(3) limpar quando o modal é dispensado

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

Se o modal não estiver em canvas cheia, aplique as ligações .modal a uma sobreposição de canvas inteira.

Minha solução para o Bootstrap 3:

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

porque para mim o único overflow: hidden na class body.modal-open não impediu que a página se body.modal-open para a esquerda devido à margin-right: 15px .

Eu não estou 100% certo de que isso funcionará com o Bootstrap, mas vale a pena tentar – ele funcionou com Remodal.js, que pode ser encontrado no github: http://vodkabears.github.io/remodal/ e faria sentido para os methods ser bem parecido.

Para parar a página que salta para o topo e também impedir a mudança direita do conteúdo, adicione uma class ao body quando o modal for acionado e defina estas regras CSS:

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

É a position:static e a height:auto que se combinam para interromper o salto do conteúdo para a direita. O overflow-y:hidden; impede que a página seja rolável por trás do modal.

Se o modal for 100% altura / largura, “mouseenter / leave” funcionará para habilitar / desabilitar facilmente a rolagem. Isso realmente funcionou para mim:

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

Eu tinha uma barra lateral que foi gerada pelo hack checkbox. Mas a idéia principal é salvar o documento scrollTop e não alterá-lo durante a rolagem da janela.

Eu simplesmente não gostei da página pulando quando o corpo se torna ‘estouro: oculto’.

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

funcionou para mim

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

A partir de novembro de 2017 Chrome introduziu uma nova propriedade css

overscroll-behavior: contain;

o que resolve esse problema, embora a escrita tenha limitado o suporte a vários navegadores.

veja abaixo links para detalhes completos e suporte ao navegador

Para o Bootstrap 3 , você pode tentar isso (trabalhando no Firefox , Chrome e Microsoft Edge ):

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

Espero que isto ajude…

Isso funcionou para mim:

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

Para aqueles que querem saber como obter o evento de rolagem para o modal bootstrap 3:

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

Esta é a melhor solução para mim:

Css:

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

E Js:

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

Eu estou usando essa function js baunilha para adicionar class “modal-aberto” ao corpo. (Baseado na resposta do 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" : ""; }; 

Escondendo o transbordamento e consertando a posição, o truque, no entanto, com o meu design fluido, iria consertá-lo além da largura dos navegadores, portanto, uma largura: 100% fixa isso.

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

Experimente este código:

 $('.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'); } });