Scrollen einfach deaktivieren, nicht ausblenden?


198

Ich versuche, die HTML / Body-Bildlaufleiste des übergeordneten Elements zu deaktivieren, während ich einen Leuchtkasten verwende. Das Hauptwort hier ist deaktivieren . Ich möchte es nicht mit verstecken overflow: hidden;.

Der Grund dafür ist, overflow: hiddendass die Site springt und den Bereich einnimmt, in dem sich die Schriftrolle befand.

Ich möchte wissen, ob es möglich ist, eine Bildlaufleiste zu deaktivieren, während sie noch angezeigt wird.


1
Sollte ein Bildlauf möglich sein? (Hat der Leuchtkasten irgendwelche Bildlaufleisten?)
Šime Vidas

Die Seite wurde gescrollt, aber ich möchte sie nur deaktivieren, während der Leuchtkasten geöffnet ist. Ich möchte nur wissen, ob es möglich ist, eine Bildlaufleiste zu deaktivieren, während sie angezeigt wird. Es wird nichts anderes benötigt, als wie es in einem Leuchtkasten oder irgendetwas anderem gemacht wird.
Dejan.S

Was ist das Problem bei der Verwendung eines Leuchtkastens mit Bildlaufleiste?
Manny

1
@Dejan Weil ich weiß , wie zu deaktivieren all Scrollen -, die die Haupt Scrollbar, sondern auch mit dem im Leuchtkasten ... deaktivieren würde
Šime Vidas

1
Bitte bearbeiten Sie die Antwort nicht zurück in diesen Beitrag. Der Antwortabschnitt unten enthält Antworten. Wenn Sie eine Antwort auf Ihre Frage haben, ist anders unten von einer Antwort, können Sie Ihre eigene Lösung in der Antwortauswahl hinzufügen.
Intcreator

Antworten:


172

Wenn die Seite unter der Überlagerung oben "fixiert" werden kann, können Sie beim Öffnen der Überlagerung festlegen

body { position: fixed; overflow-y:scroll }

Sie sollten immer noch die rechte Bildlaufleiste sehen, aber der Inhalt kann nicht gescrollt werden. Wenn Sie die Überlagerung schließen, setzen Sie diese Eigenschaften einfach mit zurück

body { position: static; overflow-y:auto }

Ich habe diesen Weg nur vorgeschlagen, weil Sie kein Bildlaufereignis ändern müssen

Aktualisieren

Sie können auch eine leichte Verbesserung vornehmen: Wenn Sie die document.documentElement.scrollTopEigenschaft kurz vor dem Öffnen der Ebene über Javascript erhalten, können Sie diesen Wert dynamisch als topEigenschaft des Body-Elements zuweisen : Bei diesem Ansatz bleibt die Seite an ihrer Stelle, unabhängig davon, ob Sie Sie sind oben oder wenn Sie bereits gescrollt haben.

Css

.noscroll { position: fixed; overflow-y:scroll }

JS

$('body').css('top', -(document.documentElement.scrollTop) + 'px')
         .addClass('noscroll');

2
Es bringt mein Layout durcheinander, aber mit einigen Änderungen könnte es funktionieren. Ich mag das, ich werde es mehr
ausprobieren

4
Mit einer kleinen Modifikation funktioniert dies. Ich habe eine Breite hinzugefügt: 100%; Ich bin weg, aktualisiere meine Frage mit der Lösung, aber du kannst deine mit der Breite ändern: 100%;? danke für den Vorschlag
Dejan.S

3
Ich weiß nicht warum, aber das funktioniert besser für mich: $('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
PDXIII

4
@whitesiroi, du hast recht. Ich habe die Geige aktualisiert: jsfiddle.net/evpozdniakov/2m8km9wg Danke!
evpozdniakov

1
Für diejenigen, die die Kommentare für eine Lösung lesen, bietet die letzte Geige eine Lösung zum Deaktivieren und erneuten Aktivieren der Bildlaufleiste, wobei in beiden Fällen die Position der Bildlaufleiste beibehalten wird. Vielen Dank!
user1063287

78

Vier kleine Ergänzungen zur ausgewählten Lösung:

  1. Wenden Sie 'noscroll' auf HTML anstatt auf body an, um doppelte Bildlaufleisten im IE zu vermeiden
  2. Um zu überprüfen , ob es tatsächlich eine Scroll - Leiste ist , bevor die ‚noscroll‘ Klasse hinzufügen. Andernfalls springt die Site auch durch die neue nicht scrollende Bildlaufleiste.
  3. Damit ein mögliches scrollTop erhalten bleibt, damit nicht die gesamte Seite nach oben zurückkehrt (wie bei Fabrizios Update, aber Sie müssen den Wert abrufen, bevor Sie die Klasse 'noscroll' hinzufügen).
  4. Nicht alle Browser behandeln scrollTop auf die gleiche Weise wie unter http://help.dottoro.com/ljnvjiow.php dokumentiert

Komplettlösung, die für die meisten Browser zu funktionieren scheint:

CSS

html.noscroll {
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

Bildlauf deaktivieren

if ($(document).height() > $(window).height()) {
     var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
     $('html').addClass('noscroll').css('top',-scrollTop);         
}

Bildlauf aktivieren

var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);

Vielen Dank an Fabrizio und Dejan, die mich auf den richtigen Weg gebracht haben, und an Brodingo für die Lösung der doppelten Bildlaufleiste


1
Dies wurde auf dem Desktop gut getestet, aber auf dem iPhone wurde ein leerer weißer Bildschirm erstellt, bis der Leser versuchte, die Seite zu scrollen. Sobald der Leser versuchte, mit der Seite zu interagieren, wurde der beabsichtigte Bildschirm mit gesperrter Schriftrolle sichtbar.
Michael Khalili

Dies funktionierte perfekt mit Fancybox auf dem iPad, um das Scrollen von Lightbox-Bildern mit afterLoad()und afterCloseRückrufen zu deaktivieren . Könnte für andere nützlich sein, die diese Frage suchen.
Tomanow

Im Teil "Bildlauf aktivieren" möchten Sie möglicherweise das Stilattribut entfernen, das nach einem Aufruf zum "Bildlauf deaktivieren" im HTML-Element platziert wird. nicht wahr?
Ben

3
jQuery standardisiert native DOMs scrollTopso, dass Zeile 2 des Codes 'Bildlauf deaktivieren' ausgedrückt werden kann als $( window ).scrollTop().
Barney

Ich denke, dass noch etwas hinzugefügt werden muss. Unter Chrome in OSX kann der Browser "überblättern", wodurch sich das Scrollen elastisch anfühlt. Mit diesem Code, wenn Sie sich im grauen Bereich über oder unter der Seite befinden und mit der Maus über eine Stelle fahren, an der Sie das Scrollen deaktivieren. Es bleibt an einer Stelle über / unter dem Browserfenster haften. Aus diesem Grund müssen Sie eine Prüfung auf einen negativen Bildlaufwert hinzufügen : if (scrollTop < 0) { scrollTop = 0; }. Hier ist der vollständige Code zum Deaktivieren von gist.github.com/jayd3e/2eefbbc571cd1668544b .
JayD3e

34

Mit jQuery inklusive:


deaktivieren

$.fn.disableScroll = function() {
    window.oldScrollPos = $(window).scrollTop();

    $(window).on('scroll.scrolldisabler',function ( event ) {
       $(window).scrollTop( window.oldScrollPos );
       event.preventDefault();
    });
};

aktivieren

$.fn.enableScroll = function() {
    $(window).off('scroll.scrolldisabler');
};

Verwendung

//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();

1
Das war perfekt für mich, die vorherige Antwort ließ meine Seite springen, diese nicht
Bogdan Tomi

Ich bin froh, dass ich helfen konnte, vielleicht müssen Sie auch nach "touchmove" suchen, für mobile Geräte,
Prost

Nun, das hat bei mir fast funktioniert. Es hat unter Windows (Firefox, Chrome) und MacOS in Firefox Wunder gewirkt ... aber dann bin ich zu Windows IE und Edge gegangen, zusammen mit MacOS in Chrome und Safari. Das Problem bestand nicht mehr darin, dass die Seite von Seite zu Seite sprang, sondern dass die Bildlaufleiste von oben nach oben sprang oder die Seite oben flackerte. Mann, das war so , so nah. Vielleicht können wir es trotzdem zum Laufen bringen.
Steven Ventimiglia

Das hat bei mir perfekt funktioniert, danke! Ideal für die Verwendung auf einer Website, auf der sich das Overlay-Menü auch am Ende der Seite befindet!
SauriolJf

12

Ich bin der OP

Mit Hilfe der Antwort von fcalderan konnte ich eine Lösung finden. Ich lasse meine Lösung hier, da sie Klarheit in die Verwendung bringt und ein sehr wichtiges Detail hinzufügt.width: 100%;

Ich füge diese Klasse hinzu

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

Das hat bei mir funktioniert und ich habe Fancyapp verwendet.


11

Das hat bei mir sehr gut funktioniert ....

// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);

// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);


// lock window scrolling
function lockScroll(e) {
    e.preventDefault();
}

Umschließen Sie diese beiden Codezeilen einfach mit dem, was Sie entscheiden, wenn Sie das Scrollen sperren möchten.

z.B

$('button').on('click', function() {
     $('body').bind('mousewheel touchmove', lockScroll);
});

Dies ist die beste Antwort von allen
Jafo

7

Sie können das Bildlaufereignis nicht deaktivieren, aber Sie können die zugehörigen Aktionen deaktivieren, die zu einem Bildlauf führen, z. B. Mausrad und Touchmove:

$('body').on('mousewheel touchmove', function(e) {
      e.preventDefault();
});

4

Sie können die Bildlaufleiste des Körpers mit ausblenden overflow: hiddenund gleichzeitig einen Rand festlegen, damit der Inhalt nicht springt:

let marginRightPx = 0;
if(window.getComputedStyle) {
    let bodyStyle = window.getComputedStyle(document.body);
    if(bodyStyle) {
        marginRightPx = parseInt(bodyStyle.marginRight, 10);
    }
}

let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
    overflow: 'hidden',
    marginRight: `${marginRightPx + scrollbarWidthPx}px`
});

Und dann können Sie der Seite eine deaktivierte Bildlaufleiste hinzufügen, um die Lücke zu füllen:

textarea {
  overflow-y: scroll;
  overflow-x: hidden;
  width: 11px;
  outline: none;
  resize: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
}
<textarea></textarea>

Genau das habe ich für meine eigene Lightbox-Implementierung getan. Scheint bisher gut zu funktionieren.


1
Diese Methode gefällt mir eigentlich am besten. Sehr einfach und funktioniert super. Vielen Dank!
Dericcain

2

Dies ist die Lösung, mit der wir uns entschieden haben. Speichern Sie einfach die Bildlaufposition, wenn das Overlay geöffnet wird, scrollen Sie jedes Mal, wenn der Benutzer versucht hat, die Seite zu scrollen, zur gespeicherten Position zurück und schalten Sie den Listener aus, wenn das Overlay geschlossen wird.

Es ist ein bisschen nervös im IE, funktioniert aber wie ein Zauber in Firefox / Chrome.

var body = $("body"),
  overlay = $("#overlay"),
  overlayShown = false,
  overlayScrollListener = null,
  overlaySavedScrollTop = 0,
  overlaySavedScrollLeft = 0;

function showOverlay() {
  overlayShown = true;

  // Show overlay
  overlay.addClass("overlay-shown");

  // Save scroll position
  overlaySavedScrollTop = body.scrollTop();
  overlaySavedScrollLeft = body.scrollLeft();

  // Listen for scroll event
  overlayScrollListener = body.scroll(function() {
    // Scroll back to saved position
    body.scrollTop(overlaySavedScrollTop);
    body.scrollLeft(overlaySavedScrollLeft);
  });
}

function hideOverlay() {
  overlayShown = false;

  // Hide overlay
  overlay.removeClass("overlay-shown");

  // Turn scroll listener off
  if (overlayScrollListener) {
    overlayScrollListener.off();
    overlayScrollListener = null;
  }
}

// Click toggles overlay
$(window).click(function() {
  if (!overlayShown) {
    showOverlay();
  } else {
    hideOverlay();
  }
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }

/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
  <h1>Top of overlay</h1>
  <p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
  <div class="spacer"></div>
  <h1>Bottom of overlay</h1>
</div>


Funktioniert zwar, verschmutzt aber das Design bei einem festen Header, da die Bildlaufleiste darunter taucht.
Leon Willens

@LeonWillens Ich bin mir nicht sicher, was du meinst. Wenn Sie Bedenken haben, dass die Überlagerung unter einem festen Header angezeigt wird, müssen Sie das z-indexvon .overlay-shownso anpassen , dass es größer als der feste Header ist. (Ich habe diesen Code in der Produktion auf einer Site mit einem festen Header ausgeführt und es funktioniert gut.)
0b10011

Nein, ich habe über die Bildlaufleiste des bodyTags gesprochen. Ich habe gestern mit Ihrem Code experimentiert und habe oben auf meiner Seite einen festen Header. Wenn ich über das bodyTag scrollen kann , befindet sich die Bildlaufleiste unter der festen Überschrift.
Leon Willens

1
@LeonWillens Ups, es sieht so aus, als hätte ich das irgendwann in der Produktion behoben und vergessen, dies zu aktualisieren. Es sieht so aus $("body"), als würden wir stattdessen verwenden $(window). Und anstatt z-index: -1auf dem Overlay, um es auszublenden, können Sie visibility: hiddenoder ähnliches verwenden. Unter jsfiddle.net/8p2gfeha finden Sie einen kurzen Test, um festzustellen , ob es funktioniert. Der feste Header wird nicht mehr oben in der Bildlaufleiste angezeigt. Ich werde schließlich versuchen, diese Änderungen in die Antwort aufzunehmen.
0b10011

Klappt wunderbar! Vielen Dank :)
Leon Willens

1

Ich hatte ein ähnliches Problem: Ein Menü auf der linken Seite, das, wenn es angezeigt wird, das Scrollen verhindert. Sobald die Höhe auf 100 VH eingestellt war, verschwand die Bildlaufleiste und der Inhalt ruckte nach rechts.

Wenn es Ihnen also nichts ausmacht, die Bildlaufleiste aktiviert zu lassen (aber das Fenster auf die volle Höhe einzustellen, damit es nirgendwo hinrollt), können Sie auch einen winzigen unteren Rand festlegen, in dem die Bildlaufleisten angezeigt werden:

body {
    height: 100vh;
    overflow: hidden;
    margin: 0 0 1px;
}

overflow:hiddenVerhindert das nicht, dass der Spielraum eine Wirkung hat?
Koja

0

Sie können den Überlauf beibehalten: ausgeblendet, aber die Bildlaufposition manuell verwalten:

Vor dem Anzeigen die tatsächliche Bildlaufposition verfolgen:

var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);

es sollte funktionieren


0

Eine grobe, aber funktionierende Methode besteht darin, den Bildlauf nach oben zu erzwingen und so das Scrollen effektiv zu deaktivieren:

var _stopScroll = false;
window.onload = function(event) {
    document.onscroll = function(ev) {
        if (_stopScroll) {
            document.body.scrollTop = "0px";
        }
    }
};

Wenn Sie den Leuchtkasten öffnen, heben Sie die Flagge und senken Sie die Flagge, wenn Sie sie schließen.

Live-Testfall .


0

Ich halte mich gerne an die Methode "Überlauf: Verborgen" und füge einfach das Auffüllen rechts hinzu, das der Breite der Bildlaufleiste entspricht.

Holen Sie sich die Funktion zur Breite der Bildlaufleiste nach lostsource .

function getScrollbarWidth() {
    var outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

    document.body.appendChild(outer);

    var widthNoScroll = outer.offsetWidth;
    // force scrollbars
    outer.style.overflow = "scroll";

    // add innerdiv
    var inner = document.createElement("div");
    inner.style.width = "100%";
    outer.appendChild(inner);        

    var widthWithScroll = inner.offsetWidth;

    // remove divs
    outer.parentNode.removeChild(outer);

    return widthNoScroll - widthWithScroll;
}

Wenn Sie das Overlay anzeigen, fügen Sie HTML die Klasse "noscroll" hinzu und fügen Sie dem Text das Auffüllrecht hinzu:

$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");

Entfernen Sie beim Ausblenden die Klasse und die Polsterung:

$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);

Der Noscroll-Stil ist genau das:

.noscroll { overflow: hidden; }

Beachten Sie, dass Sie, wenn Sie Elemente mit der Position: fest haben, die Auffüllung auch diesen Elementen hinzufügen müssen.


Ich habe diese Lösung verwendet. Es hat mir geholfen, doppelte Bildlaufleisten zu vermeiden (eine "leer" für den Körper und eine zweite für den Inhalt der Überlagerung). Es funktioniert auch sehr gut unter OSX, wo möglicherweise Bildlaufleisten angezeigt werden oder nicht.
Novazembla

0

<div id="lightbox">befindet sich innerhalb des <body>Elements. Wenn Sie also durch den Leuchtkasten scrollen, scrollen Sie auch durch den Körper. Die Lösung besteht darin, das <body>Element nicht über 100% zu erweitern, den langen Inhalt in einem anderen divElement zu platzieren und diesem divElement bei Bedarf eine Bildlaufleiste hinzuzufügen overflow: auto.

html {
  height: 100%
}
body {
  margin: 0;
  height: 100%
}
#content {
  height: 100%;
  overflow: auto;
}
#lightbox {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
<html>
  <body>
    <div id="content">much content</div>
    <div id="lightbox">lightbox<div>
  </body>
</html>

Das Scrollen über den Leuchtkasten (und auch den body) hat keine Auswirkung, da der Körper nicht länger als 100% der Bildschirmhöhe ist.


0

Alle Modal / Lightbox-Javascript-basierten Systeme verwenden einen Überlauf, wenn die Modal / Lightbox auf einem HTML-Tag oder einem Body-Tag angezeigt wird.

Wenn der Leuchtkasten angezeigt wird, drücken die js einen Überlauf, der auf HTML oder Body-Tag verborgen ist. Wenn der Leuchtkasten ausgeblendet ist, entfernen einige den ausgeblendeten anderen und drücken einen automatischen Überlauf auf HTML oder Body-Tag.

Entwickler, die auf einem Mac arbeiten, sehen das Problem der Bildlaufleiste nicht.

Ersetzen Sie einfach das Versteckte durch ein Nicht-Set, damit der Inhalt nicht unter das Modal des Entfernens der Bildlaufleiste rutscht.

Leuchtkasten öffnen / zeigen:

<html style="overflow: unset;"></html>

Leuchtkasten schließen / verstecken:

<html style="overflow: auto;"></html>

0

Wenn die Seite unter der Überlagerung oben "fixiert" werden kann, können Sie beim Öffnen der Überlagerung festlegen

.disableScroll { position: fixed; overflow-y:scroll }

Wenn Sie diese Klasse für den scrollbaren Körper bereitstellen, sollte die rechte Bildlaufleiste weiterhin angezeigt werden, der Inhalt ist jedoch nicht scrollbar.

Um die Position der Seite beizubehalten, führen Sie dies in jquery aus

$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');

Wenn Sie die Überlagerung schließen, setzen Sie diese Eigenschaften einfach mit zurück

var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));

Ich habe diesen Weg nur vorgeschlagen, weil Sie kein Bildlaufereignis ändern müssen


0

Dadurch wird verhindert, dass das Ansichtsfenster nach oben springt, indem die Bildlaufposition gespeichert und beim Aktivieren des Bildlaufs wiederhergestellt wird.

CSS

.no-scroll{
  position: fixed; 
  width:100%;
  min-height:100vh;
  top:0;
  left:0;
  overflow-y:scroll!important;
}

JS

var scrollTopPostion = 0;

function scroll_pause(){
  scrollTopPostion = $(window).scrollTop();
  $("body").addClass("no-scroll").css({"top":-1*scrollTopPostion+"px"});
}

function scroll_resume(){
  $("body").removeClass("no-scroll").removeAttr("style");
  $(window).scrollTop(scrollTopPostion);
}

Jetzt müssen Sie nur noch die Funktionen aufrufen

$(document).on("click","#DISABLEelementID",function(){
   scroll_pause();
});

$(document).on("click","#ENABLEelementID",function(){
   scroll_resume();
});

-1

Sie können es mit Javascript tun:

// Classic JS
window.onscroll = function(ev) {
  ev.preventDefault();
}

// jQuery
$(window).scroll(function(ev) {
  ev.preventDefault();
}

Deaktivieren Sie es dann, wenn Ihr Leuchtkasten geschlossen ist.

Wenn Ihr Leuchtkasten jedoch eine Bildlaufleiste enthält, können Sie nicht scrollen, solange er geöffnet ist. Dies liegt daran, dass windowbeide bodyund enthalten #lightbox. Sie müssen also eine Architektur wie die folgende verwenden:

<body>
  <div id="global"></div>
  <div id="lightbox"></div>
</body>

Und dann wenden Sie die onscrollVeranstaltung nur auf #global.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.