Impedire a BODY di scorrere quando viene aperta una modal

Voglio che il mio corpo smetta di scorrere quando si utilizza la rotellina del mouse mentre è aperto il Modale (da http://twitter.github.com/bootstrap ) sul mio sito web.

Ho provato a chiamare il pezzo di javascript qui sotto quando la modal è stata aperta ma senza successo

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

Si prega di notare che il nostro sito Web ha abbandonato il supporto per IE6, tuttavia IE7 + deve essere compatibile.

Il modal Bootstrap aggiunge automaticamente la class modal-open al corpo quando viene visualizzata una finestra di dialogo modale e la rimuove quando la finestra di dialogo è nascosta. Puoi quindi aggiungere quanto segue al tuo CSS:

 body.modal-open { overflow: hidden; } 

Si potrebbe obiettare che il codice precedente appartiene alla base del codice CSS Bootstrap, ma questa è una soluzione facile da aggiungere al tuo sito.

Aggiornamento 8 febbraio 2013
Questo ha smesso di funzionare su Twitter Boostrap v. 2.3.0 – non aggiungono più la class modal-open al corpo.

Una soluzione alternativa sarebbe quella di aggiungere la class al corpo quando la modale sta per essere mostrata e rimuoverla quando la modale è chiusa:

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

Aggiornamento 11 marzo 2013 Sembra che la class modal-open ritorni in Bootstrap 3.0, esplicitamente allo scopo di impedire lo scorrimento:

Reintroduce .modal-open sul corpo (in modo da poter nuotare il rotolo lì)

Vedi questo: https://github.com/twitter/bootstrap/pull/6342 – guarda la sezione Modale .

La risposta accettata non funziona su dispositivi mobili (iOS 7 con Safari 7, almeno) e non desidero JavaScript MOAR in esecuzione sul mio sito quando CSS lo farà.

Questo CSS impedirà lo scorrimento della pagina di sfondo sotto il modale:

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

Tuttavia, ha anche un leggero effetto collaterale di scorrere essenzialmente verso l’alto. position:absolute risolve questo, ma reintroduce la possibilità di scorrere su mobile.

Se conosci il tuo viewport (il mio plugin per l’aggiunta di viewport al ) puoi semplicemente aggiungere un interruttore css per la 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; } 

Aggiungo anche questo per evitare che la pagina sottostante salti a sinistra / destra quando mostra / nasconde le modali.

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

questa risposta è un x-post.

Semplicemente hide il troppo pieno del corpo e rende il corpo non a scorrere. Quando nascondi il modale, ripristinalo in automatico.

Ecco il codice:

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

Puoi provare ad impostare le dimensioni del corpo in base alle dimensioni della finestra con overflow: nascosto quando modale è aperto

Avvertenza: l’opzione seguente non è rilevante per Bootstrap v3.0.x, poiché lo scorrimento in quelle versioni è stato esplicitamente limitato al modale stesso. Se disabiliti gli eventi wheel, potresti inavvertitamente impedire ad alcuni utenti di visualizzare il contenuto in modali con altezze maggiori rispetto all’altezza viewport.


Ancora un’altra opzione: Wheel Events

L’evento di scorrimento non è cancellabile. Tuttavia è ansible annullare la rotellina della ruota e gli eventi della ruota . Il grande avvertimento è che non tutti i browser legacy li supportano, Mozilla solo recentemente ha aggiunto il supporto per quest’ultimo in Gecko 17.0. Non conosco la diffusione completa, ma IE6 + e Chrome li supportano.

Ecco come sfruttarli:

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

JSFiddle

Devi andare oltre la risposta di @ charlietfl e tenere conto delle barre di scorrimento, altrimenti potresti vedere un reflow del documento.

Aprendo il modale:

  1. Registra la larghezza del body
  2. Imposta overflow del body su hidden
  3. Impostare esplicitamente la larghezza del corpo su ciò che era nel passaggio 1.

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

Chiusura del modal:

  1. Imposta overflow del body su auto
  2. Imposta la larghezza del body su auto

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

Ispirato da: 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(); }); }); 

Prova questo:

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

ha funzionato per me (supporta IE8)

Non sono sicuro di questo codice, ma ne vale la pena.

In jQuery:

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

Come ho detto prima, non sono sicuro al 100% ma provo comunque.

Non è ansible farlo funzionare su Chrome semplicemente cambiando CSS, perché non volevo che la pagina tornasse in cima. Questo ha funzionato bene:

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

Aggiungere la class ‘is-modal-open’ o modificare lo stile del body tag con javascript è ok e funzionerà come dovrebbe. Ma il problema che dovremo affrontare è quando il corpo diventa overflow: nascosto, salterà in cima, (scrollTop diventerà 0). Questo diventerà un problema di usabilità in seguito.

Come soluzione per questo problema, invece di cambiare l’overflow del tag body: nascosto cambiarlo sul tag html

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

Potresti usare la seguente logica, l’ho provato e funziona (anche in IE)

     
































































La soluzione migliore è la soluzione di css-only body{overflow:hidden} utilizzata dalla maggior parte di queste risposte. Alcune risposte forniscono una correzione che impedisce anche il “salto” causato dalla barra di scorrimento scomparsa; tuttavia, nessuno era troppo elegante. Quindi, ho scritto queste due funzioni e sembrano funzionare piuttosto bene.

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

Dai un’occhiata a questo jsFiddle per vederlo in uso.

Basato su questo violino: http://jsfiddle.net/dh834zgw/1/

il seguente snippet (usando jquery) disabiliterà lo scroll della finestra:

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

E nel tuo css:

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

Ora quando rimuovi la modale, non dimenticare di rimuovere la class noscroll sul tag html:

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

Purtroppo nessuna delle risposte precedenti ha risolto i miei problemi.

Nella mia situazione, la pagina web originariamente ha una barra di scorrimento. Ogni volta che clicco sul modale, la barra di scorrimento non scompare e l’intestazione si sposta a destra di un bit.

Poi ho provato ad aggiungere .modal-open{overflow:auto;} (che la maggior parte delle persone raccomandava). Ha risolto i problemi: la barra di scorrimento appare dopo aver aperto la modal. Tuttavia, emerge un altro effetto collaterale che è che “lo sfondo sotto l’intestazione si sposta leggermente verso sinistra, insieme ad un’altra lunga barra dietro il modale”

Long bar dietro modale

Fortunatamente, dopo aver aggiunto {padding-right: 0 !important;} , tutto è stato risolto perfettamente. Sia l’intestazione che lo sfondo del corpo non si sono mossi e il modale mantiene ancora la barra di scorrimento.

Immagine fissa

Spero che questo possa aiutare coloro che sono ancora bloccati con questo problema. In bocca al lupo!

Molti suggeriscono “overflow: hidden” sul corpo, che non funzionerà (non nel mio caso almeno), dal momento che farà scorrere il sito verso l’alto.

Questa è la soluzione che funziona per me (sia su telefoni cellulari che computer), 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'); }); 

Questo farà in modo che lo scorrimento del modal funzioni e impedisca al sito di scorrere allo stesso tempo.

La maggior parte dei pezzi sono qui, ma non vedo nessuna risposta che metta tutto insieme.

Il problema è triplice.

(1) impedire lo scorrimento della pagina sottostante

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

(2) e rimuovere la barra di scorrimento

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

(3) ripulire quando la modale viene chiusa

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

Se la modale non è a schermo intero, applica i collegamenti .modal a una sovrapposizione a schermo intero.

La mia soluzione per Bootstrap 3:

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

perché per me l’unico overflow: hidden nella class body.modal-open non ha impedito alla pagina di spostarsi a sinistra a causa del margin-right: 15px originale margin-right: 15px .

Non sono sicuro al 100% che funzioni con Bootstrap, ma vale la pena provarlo: ha funzionato con Remodal.js che può essere trovato su github: http://vodkabears.github.io/remodal/ e avrebbe senso per i metodi per essere abbastanza simili.

Per evitare che la pagina salti in cima e impedisca il corretto spostamento del contenuto, aggiungi una class al body quando viene triggersta la modal e imposta le seguenti regole CSS:

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

È la position:static e l’ height:auto che si combinano per fermare il salto del contenuto a destra. L’ overflow-y:hidden; impedisce alla pagina di essere scorrevole dietro il modal.

Se modale è 100% altezza / larghezza, “mouseenter / leave” funzionerà per abilitare / disabilitare facilmente lo scorrimento. Questo ha funzionato davvero per me:

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

Ho avuto una barra laterale che è stata generata dalla casella di controllo hack. Ma l’idea principale è salvare il documento scrollTop e non cambiarlo durante lo scorrimento della finestra.

Non mi piace che la pagina salti quando il corpo diventa “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); } }); }) }); 

ha funzionato per me

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

A partire da novembre 2017, Chrome ha introdotto una nuova proprietà css

overscroll-behavior: contain;

che risolve questo problema anche se al momento della scrittura ha un supporto cross browser limitato.

vedere sotto i collegamenti per i dettagli completi e il supporto del browser

Per Bootstrap 3 , puoi provare questo (lavorando su Firefox , Chrome e Microsoft Edge ):

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

Spero che questo ti aiuti…

Questo ha funzionato per me:

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

Per chi si chiede come ottenere l’evento scroll per il modal bootstrap 3:

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

Questa è la soluzione migliore per me:

Css:

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

E Js:

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

Sto usando questa funzione vanilla js per aggiungere una class “modal-open” al corpo. (Basato sulla risposta di 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" : ""; }; 

Nascondere il troppopieno e fissare la posizione fa il trucco, tuttavia con il mio design fluido lo sistemerebbe oltre la larghezza del browser, quindi una larghezza: 100% fisso.

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

Prova questo codice:

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