J'essaie de désactiver la barre de défilement html/body du parent lorsque j'utilise une lightbox. Le mot principal ici est disable . Je veux pas veux le cacher avec overflow: hidden;
.
La raison en est que overflow: hidden
fait sauter le site et occupe la zone où se trouvait le parchemin.
Je veux savoir s'il est possible de désactiver une barre de défilement tout en la montrant.
Si la page sous la superposition peut être "fixée" en haut, vous pouvez définir lorsque vous ouvrez la superposition
body { position: fixed; overflow-y:scroll }
vous devriez toujours voir la barre de défilement de droite, mais le contenu ne peut pas défiler. Lorsque vous fermez la superposition, rétablissez ces propriétés avec
body { position: static; overflow-y:auto }
Je viens de proposer cette façon uniquement parce que vous n'avez pas besoin de changer un événement de défilement
Mettre à jour
Vous pouvez également faire une légère amélioration: si vous obtenez la propriété document.documentElement.scrollTop
via javascript juste avant l'ouverture du calque, vous pouvez affecter cette valeur de manière dynamique à la propriété top
de l'élément body: avec cette approche, la page restera à sa place, peu importe si vous êtes au top ou si vous avez déjà fait défiler.
Css
.noscroll { position: fixed; overflow-y:scroll }
JS
$('body').css('top', -(document.documentElement.scrollTop) + 'px')
.addClass('noscroll');
Quatre petits ajouts à la solution sélectionnée:
Solution complète qui semble fonctionner pour la plupart des navigateurs:
CSS
html.noscroll {
position: fixed;
overflow-y: scroll;
width: 100%;
}
Désactiver le défilement
if ($(document).height() > $(window).height()) {
var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
$('html').addClass('noscroll').css('top',-scrollTop);
}
Activer le défilement
var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);
Merci à Fabrizio et Dejan de m'avoir mis sur la bonne voie et à Brodingo pour la solution à la double barre de défilement
$.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();
Cela a très bien fonctionné pour moi ....
// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);
// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);
// lock window scrolling
function lockScroll(e) {
e.preventDefault();
}
enveloppez ces deux lignes de code avec ce que vous voulez quand vous voulez verrouiller le défilement.
par exemple.
$('button').on('click', function() {
$('body').bind('mousewheel touchmove', lockScroll);
});
Vous ne pouvez pas désactiver l'événement de défilement, mais vous pouvez également désactiver les actions associées qui entraînent un défilement, comme molette de la souris et touchmove:
$('body').on('mousewheel touchmove', function(e) {
e.preventDefault();
});
Je suis l'OP
Avec l'aide de fcalderan, j'ai pu résoudre le problème. Je laisse ma solution ici car elle clarifie son utilisation et ajoute un détail très crucial, width: 100%;
J'ajoute cette classe
body.noscroll
{
position: fixed;
overflow-y: scroll;
width: 100%;
}
cela a fonctionné pour moi et j'utilisais Fancyapp.
Alternativement, vous pouvez masquer la barre de défilement du corps avec overflow: hidden
et définir une marge en même temps pour que le contenu ne saute pas:
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`
});
Et vous pouvez ensuite ajouter une barre de défilement désactivée à la page pour combler le vide:
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>
Je l'ai fait exactement pour ma propre implémentation lightbox. Semble fonctionner bien jusqu'à présent.
C'est la solution avec laquelle nous sommes allés. Enregistrez simplement la position de défilement lorsque la superposition est ouverte, revenez à la position enregistrée chaque fois que l'utilisateur tente de faire défiler la page et désactivez l'écouteur lorsque la superposition est fermée.
C'est un peu nerveux sur IE, mais fonctionne comme un charme sur 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>
J'ai eu un problème similaire: un menu de gauche qui, lorsqu'il apparaît, empêche le défilement. Dès que la hauteur a été réglée sur 100vh, la barre de défilement a disparu et le contenu a été agité à droite.
Donc, si cela ne vous dérange pas de laisser la barre de défilement activée (mais si vous définissez la fenêtre à pleine hauteur pour qu'elle ne défilera pas réellement), une autre possibilité consiste à définir une petite marge inférieure, qui conservera les barres de défilement suivantes:
body {
height: 100vh;
overflow: hidden;
margin: 0 0 1px;
}
La méthode la plus simple mais la plus efficace consiste à forcer le défilement vers le haut, désactivant ainsi le défilement:
var _stopScroll = false;
window.onload = function(event) {
document.onscroll = function(ev) {
if (_stopScroll) {
document.body.scrollTop = "0px";
}
}
};
Lorsque vous ouvrez la visionneuse, relevez le drapeau et, pour le fermer, abaissez-le.
<div id="lightbox">
est à l'intérieur de l'élément <body>
. Ainsi, lorsque vous faites défiler la visionneuse, vous faites également défiler le corps. La solution consiste à ne pas étendre l'élément <body>
à 100%, à placer le contenu long dans un autre élément div
et à ajouter une barre de défilement si nécessaire à cet élément div
avec 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>
Maintenant, le défilement sur la lightbox (ainsi que sur la body
) n'a aucun effet, car le corps ne dépasse pas 100% de la hauteur de l'écran.
Si la page sous la superposition peut être "fixée" en haut, vous pouvez définir lorsque vous ouvrez la superposition
.disableScroll { position: fixed; overflow-y:scroll }
si vous fournissez cette classe au corps déroulant, vous devriez toujours voir la barre de défilement de droite, mais le contenu ne peut pas faire défiler.
Pour maintenir la position de la page, faites ceci dans jQuery
$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');
Lorsque vous fermez la superposition, rétablissez ces propriétés avec
var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));
Je viens de proposer cette façon uniquement parce que vous n'avez pas besoin de changer un événement de défilement
Tous les systèmes basés sur JavaScript modal/lightbox utilisent un débordement lors de l'affichage de la modal/lightbox, sur une balise html ou une balise body.
Lorsque la visionneuse est allumée, la commande js pousse un débordement masqué sur une balise html ou body . Lorsque la visionneuse est masquée, certaines suppriment le cache caché.
Les développeurs qui travaillent sur Mac ne voient pas le problème de la barre de défilement.
Il suffit de remplacer le masqué par un non défini pour ne pas voir le contenu glisser sous la modale suppression de la barre de défilement.
Visionneuse ouverte/spectacle:
<html style="overflow: unset;"></html>
Visionneuse fermer/cacher:
<html style="overflow: auto;"></html>
J'aime m'en tenir à la méthode "overflow: hidden" et ajouter juste un padding-right égal à la largeur de la barre de défilement.
Obtenir la fonction de largeur de la barre de défilement, par 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;
}
Lorsque vous affichez la superposition, ajoutez la classe "noscroll" au code HTML et ajoutez padding-right au body:
$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");
Lorsque vous vous cachez, supprimez la classe et le rembourrage:
$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);
Le style noscroll est juste ceci:
.noscroll { overflow: hidden; }
Notez que si vous avez des éléments avec position: fixed, vous devez également ajouter le remplissage à ces éléments.
vous pouvez garder le débordement: masqué mais gérer la position du défilement manuellement:
avant d'afficher garder trace de la position actuelle du défilement:
var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);
ça devrait marcher