Ich versuche, die HTML/Body-Bildlaufleiste des übergeordneten Elements zu deaktivieren, während ich einen Leuchtkasten verwende. Das Hauptwort hier ist disable . Ich will nicht will es mit overflow: hidden;
verstecken.
Der Grund dafür ist, dass overflow: hidden
die Site springt und den Bereich aufnimmt, in dem sich der Bildlauf befand.
Ich möchte wissen, ob es möglich ist, eine Bildlaufleiste zu deaktivieren, während sie noch angezeigt wird.
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, der Inhalt kann jedoch 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
Update
Sie können auch eine geringfügige Verbesserung vornehmen: Wenn Sie die document.documentElement.scrollTop
-Eigenschaft über Javascript direkt vor dem Öffnen der Ebene erhalten, können Sie diesen Wert dynamisch als top
-Eigenschaft des body-Elements zuweisen 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');
Vier kleine Ergänzungen zur ausgewählten Lösung:
Komplette Lösung, die für die meisten Browser zu funktionieren scheint:
CSS
html.noscroll {
position: fixed;
overflow-y: scroll;
width: 100%;
}
Scroll 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);
}
Scroll 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 für die doppelte Bildlaufleiste
$.fn.disableScroll = function() {
window.oldScrollPos = $(window).scrollTop();
$(window).on('scroll.scrolldisabler',function ( event ) {
$(window).scrollTop( window.oldScrollPos );
event.preventDefault();
});
};
$.fn.enableScroll = function() {
$(window).off('scroll.scrolldisabler');
};
//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();
Das hat wirklich gut für mich funktioniert ....
// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);
// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);
// lock window scrolling
function lockScroll(e) {
e.preventDefault();
}
umhüllen Sie diese beiden Codezeilen einfach mit der Entscheidung, wann Sie das Scrollen blockieren möchten.
z.B.
$('button').on('click', function() {
$('body').bind('mousewheel touchmove', lockScroll);
});
Sie können das Bildlaufereignis nicht deaktivieren, aber Sie können die verwandten Aktionen, die zu einem Bildlauf führen, wie Mausrad und Touchmove, deaktivieren:
$('body').on('mousewheel touchmove', function(e) {
e.preventDefault();
});
Ich bin die OP
Mit Hilfe von answer von fcalderan konnte ich eine Lösung finden. Ich lasse meine Lösung hier, da sie Klarheit in der 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 funktionierte für mich und ich verwendete Fancyapp.
Alternativ können Sie die Bildlaufleiste des Körpers mit overflow: hidden
ausblenden und 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 gemacht. Scheint so gut zu funktionieren.
Dies ist die Lösung, mit der wir gegangen sind. Speichern Sie einfach die Bildlaufposition, wenn die Überlagerung geöffnet ist, blättern Sie bei jedem Versuch des Benutzers, die Seite zu scrollen, zurück zur gespeicherten Position, und schalten Sie den Listener aus, wenn die Überlagerung geschlossen wird.
Es ist ein wenig 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>
Ich hatte ein ähnliches Problem: ein Menü auf der linken Seite, das das Blättern verhindert, wenn es erscheint. Sobald die Höhe auf 100 vh eingestellt war, verschwand die Bildlaufleiste und der Inhalt ruckte nach rechts.
Wenn Sie also nichts dagegen haben, die Bildlaufleiste aktiviert zu lassen (aber das Fenster auf die volle Höhe einstellen, damit es nicht wirklich irgendwo rollen kann), besteht die Möglichkeit, einen winzigen unteren Rand festzulegen, der die Bildlaufleisten anzeigen lässt:
body {
height: 100vh;
overflow: hidden;
margin: 0 0 1px;
}
Eine grobe Arbeitsweise besteht jedoch darin, den Bildlauf nach oben zu zwingen, wodurch der Bildlauf effektiv deaktiviert wird:
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 Fahne an und senken Sie die Fahne, wenn Sie sie schließen.
<div id="lightbox">
befindet sich innerhalb des <body>
-Elements. Wenn Sie also den Leuchtkasten scrollen, scrollen Sie auch den Hauptteil. Die Lösung besteht darin, das <body>
-Element nicht über 100% zu erweitern, den langen Inhalt in ein anderes div
-Element zu platzieren und bei Bedarf diesem div
-Element mit overflow: auto
eine Bildlaufleiste hinzuzufügen.
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 die Lightbox (und auch die Variable body
) hat jetzt keine Auswirkungen, da der Körper nicht mehr als 100% der Bildschirmhöhe beträgt.
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 zwar immer noch die rechte Bildlaufleiste angezeigt werden, der Inhalt kann jedoch nicht gescrollt werden.
Um die Position der Seite beizubehalten, tun Sie dies in jquery
$('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
Alle Javascript-basierten Systeme auf Modal-/Leuchtkasten verwenden einen Überlauf, wenn die Modal-/Lightbox, das HTML-Tag oder das Body-Tag angezeigt wird.
Wenn der Leuchtkasten angezeigt wird, wird der js Push-Überlauf für HTML oder Body-Tag ausgeblendet. Wenn ein Lightbox ausgeblendet ist, entfernen einige den ausgeblendeten Push-Überlauf automatisch für HTML oder Body-Tag.
Entwickler, die unter Mac arbeiten, sehen das Problem der Bildlaufleiste nicht.
Ersetzen Sie einfach das ausgeblendete durch ein nicht festgelegtes Element, damit der Inhalt nicht unter dem Modal des Entfernens der Bildlaufleiste angezeigt wird.
Lightbox öffnen/anzeigen:
<html style="overflow: unset;"></html>
Lightbox schließen/verbergen:
<html style="overflow: auto;"></html>
Ich bleibe gerne bei der "overflow: hidden" -Methode und füge einfach eine Auffüll-Rechte hinzu, die der Bildlaufleistenbreite entspricht.
Funktion zum Abrufen der Bildlaufleiste durch 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 "noscroll" -Klasse zu html hinzu und fügen Sie dem Körper ein Füllzeichen hinzu:
$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");
Entfernen Sie die Klasse und die Auffüllung beim Ausblenden:
$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);
Der Noscroll-Stil ist genau dieser:
.noscroll { overflow: hidden; }
Wenn Sie Elemente mit position: fixed haben, müssen Sie die Auffüllung auch zu diesen Elementen hinzufügen.
sie können den Überlauf beibehalten: ausgeblendet, die Bildlaufposition jedoch manuell verwalten:
vor dem Anzeigen der aktuellen Scrollposition nachverfolgen:
var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);
es sollte funktionieren