Juste désactiver scroll, pas le cacher?
j'essaie de désactiver la barre de défilement html/body du parent pendant que j'utilise une lightbox. Le mot principal ici est disable . Je ne pas veux le cacher avec overflow: hidden;
.
la raison en est que overflow: hidden
fait le saut du site et de prendre la zone où le rouleau était.
je veux savoir s'il est possible de désactiver un scrollbar tout en le montrant.
14 réponses
si la page sous la couche supérieure peut être "corrigée" en haut, lorsque vous ouvrez la couche supérieure vous pouvez définir
body { position: fixed; overflow-y:scroll }
vous devriez toujours voir le scrollbar droit, mais le contenu n'est pas scrollable. Lorsque vous fermez la superposition revenir à ces propriétés avec
body { position: static; overflow-y:auto }
je viens de proposer cette façon seulement parce que vous n'auriez pas besoin de changer n'importe quel événement de défilement
mise à 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 de la couche, vous pouvez dynamiquement attribuer cette valeur comme top
propriété de l'élément de corps: avec cette approche, la page se tiendra à sa place, peu importe si vous êtes au-dessus ou si vous avez déjà défilé.
Css
.noscroll { position: fixed; overflow-y:scroll }
JS
$('body').css('top', -(document.documentElement.scrollTop) + 'px')
.addClass('noscroll');
quatre petits ajouts à la solution choisie:
- Appliquer "noscroll' html au lieu de au corps afin d'éviter la double barres de défilement dans IE
- à Vérifiez s'il y a réellement une barre de défilement avant d'ajouter la classe "noscroll". Sinon, le site sautera également poussé par la nouvelle barre de défilement Non défilante.
- Pour garder l'éventuel scrollTop ainsi, la page entière ne retourne pas en haut (comme la mise à jour de Fabrizio, mais vous devez saisir la valeur avant d'ajouter la classe "noscroll")
- tous les navigateurs ne gèrent pas scrollTop de la même manière que celui décrit à http://help.dottoro.com/ljnvjiow.php
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 pour m'avoir mis sur la bonne voie et à Brodingo pour la solution à la barre de rouleau double
avec jQuery inclus:
désactiver
$.fn.disableScroll = function() {
window.oldScrollPos = $(window).scrollTop();
$(window).on('scroll.scrolldisabler',function ( event ) {
$(window).scrollTop( window.oldScrollPos );
event.preventDefault();
});
};
activer
$.fn.enableScroll = function() {
$(window).off('scroll.scrolldisabler');
};
utilisation
//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();
cela a vraiment 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();
}
juste envelopper ces deux lignes de code avec ce qui décide quand vous allez à verrouiller le défilement.
p.ex.
$('button').on('click', function() {
$('body').bind('mousewheel touchmove', lockScroll);
});
vous ne pouvez pas désactiver l'événement scroll, mais vous pouvez désactiver les actions connexes qui mènent à un scroll, comme mousewheel et touchmove:
$('body').on('mousewheel touchmove', function(e) {
e.preventDefault();
});
alternativement, vous pouvez cacher la barre de défilement du corps avec overflow: hidden
et mettre une marge en même temps afin 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 ensuite vous pouvez ajouter un scrollbar désactivé à 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>
j'ai fait exactement cela pour ma propre implémentation de lightbox. Semble bien fonctionner jusqu'à présent.
C'est la solution que nous avons adoptée. Il suffit de sauvegarder la position de défilement lorsque la superposition est ouverte, de faire défiler vers la position sauvegardée à chaque fois que l'Utilisateur a essayé de faire défiler la page, et de désactiver 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>
je suis l'OP
avec l'aide de réponse de fcalderan j'ai pu former une solution. Je laisse ma solution ici car elle apporte la clarté à la façon de l'utiliser, et ajoute un détail très crusial, width: 100%;
j'ajoute cette classe
body.noscroll
{
position: fixed;
overflow-y: scroll;
width: 100%;
}
ça a marché pour moi et J'utilisais Fancyapp.
j'ai eu un problème similaire: un menu de gauche qui, lorsqu'il apparaît, empêche de défilement. Dès que la hauteur a été réglée à 100 VH, le scrollbar a disparu et le contenu a secoué à droite.
donc si vous ne vous gênez pas de garder la barre de défilement activée (mais de mettre la fenêtre à pleine hauteur pour qu'elle ne défile nulle part) alors une autre possibilité est de définir une marge infime, qui gardera les barres de défilement montrant:
body {
height: 100vh;
overflow: hidden;
margin: 0 0 1px;
}
vous pouvez garder le débordement: caché mais gérer la position de défilement manuellement:
avant de montrer garder trace de la position actuelle du rouleau:
var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);
il doit travailler
Brut mais la façon de travailler sera de forcer l'défiler l'écran vers le haut, donc la désactivation de défilement:
var _stopScroll = false;
window.onload = function(event) {
document.onscroll = function(ev) {
if (_stopScroll) {
document.body.scrollTop = "0px";
}
}
};
lorsque vous ouvrez la lightbox,levez le drapeau et lorsque vous le fermez, baissez le drapeau.
"151960920 Vivre" cas de test .
j'aime m'en tenir à la méthode" overflow: hidden " et juste ajouter le rembourrage-droit qui est égal à la largeur de la barre de défilement.
Obtenir la barre de défilement de la largeur de la fonction, 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;
}
lors de l'affichage de la superposition, ajouter la classe "noscroll" au html et ajouter le rembourrage-droit au corps:
$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");
lors de la dissimulation, supprimer la classe et le rembourrage:
$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);
La noscroll style est juste ceci:
.noscroll { overflow: hidden; }
Notez que si vous avez des éléments avec position:fixed, vous devez ajouter le rembourrage de ces éléments.
<div id="lightbox">
est à l'intérieur de l'élément <body>
, donc quand vous faites défiler la lightbox vous faites aussi défiler le corps. La solution est de ne pas étendre l'élément <body>
à plus de 100%, de placer le long contenu dans un autre élément div
et d'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, défilant au-dessus de la lightbox (et le body
ainsi) n'a pas effet, parce que le corps n'est pas plus de 100% de la hauteur de l'écran.
vous pouvez le faire avec Javascript:
// Classic JS
window.onscroll = function(ev) {
ev.preventDefault();
}
// jQuery
$(window).scroll(function(ev) {
ev.preventDefault();
}
puis désactivez-le lorsque votre lightbox est fermée.
mais si votre lightbox contient une barre de défilement, vous ne pourrez pas défiler tant qu'elle est ouverte. Cela est dû au fait que window
contient à la fois body
et #lightbox
.
Vous devez donc utiliser une architecture comme celle-ci:
<body>
<div id="global"></div>
<div id="lightbox"></div>
</body>
et ensuite appliquer l'événement onscroll
uniquement sur #global
.