web-dev-qa-db-fra.com

Il suffit de désactiver le défilement pour ne pas le cacher?

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.

166
Dejan.S

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');
145
fcalderan

Quatre petits ajouts à la solution sélectionnée:

  1. Appliquez 'noscroll' à html au lieu de body pour éviter les doubles barres de défilement dans IE
  2. To vérifiez s'il y a réellement une barre de défilement avant d'ajouter la classe 'noscroll'. Dans le cas contraire, le site sautera également par la nouvelle barre de défilement sans défilement.
  3. Pour garder les scrollTop possibles afin que la page entière ne retourne pas au début (comme la mise à jour de Fabrizio, mais vous devez récupérer la valeur avant d'ajouter la classe 'noscroll')
  4. Tous les navigateurs ne gèrent pas scrollTop de la même manière que celle décrite à 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 de m'avoir mis sur la bonne voie et à Brodingo pour la solution à la double barre de défilement

73
Mike Garcia

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');
};

usage

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

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);
});
7
dmackenz

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();
});
6
tocqueville

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.

5
Dejan.S

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.

3
mpen

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>

2
0b10011

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;
}
1
dhc

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.

Cas de test en direct .

0
Shadow Wizard

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

0
Marek C

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

0
Bhuvan Arora

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>
0
Vizor

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.

0
Janne Annala

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

0
malko