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.

159
demandé sur AJNeufeld 2012-01-02 18:01:46

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');
137
répondu fcalderan 2016-11-02 08:56:35

quatre petits ajouts à la solution choisie:

  1. Appliquer "noscroll' html au lieu de au corps afin d'éviter la double barres de défilement dans IE
  2. à 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.
  3. 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")
  4. 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

68
répondu Mike Garcia 2013-02-28 08:08:59

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();
28
répondu ceed 2016-02-08 21:02:44

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);
});
7
répondu dmackenz 2017-08-17 14:49:17

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();
});
5
répondu tocqueville 2016-07-22 13:19:51

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.

3
répondu mpen 2016-09-23 20:54:43

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>
2
répondu 0b10011 2014-09-26 21:02:44

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.

2
répondu Dejan.S 2016-07-23 07:51:38

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;
}
1
répondu dhc 2016-09-30 20:19:07

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

0
répondu malko 2012-01-02 14:22:33

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 .

0
répondu Shadow Wizard 2012-01-02 14:26:21

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.

0
répondu Janne Annala 2017-05-23 11:47:26

<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.

0
répondu Marek C 2015-10-04 16:28:06

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 .

-1
répondu Loïs Di Qual 2012-01-02 14:20:07