Comment désactiver par programme le défilement de page avec jQuery


163

En utilisant jQuery, je voudrais désactiver le défilement du corps:

Mon idée est de:

  1. Ensemble body{ overflow: hidden;}
  2. Capturez le courant scrollTop();/scrollLeft()
  3. Liez à l'événement de défilement du corps, définissez scrollTop / scrollLeft sur la valeur capturée.

Y a-t-il un meilleur moyen?


Mettre à jour:

Veuillez consulter mon exemple, et une raison pour laquelle, sur http://jsbin.com/ikuma4/2/edit

Je suis conscient que quelqu'un se demandera "pourquoi n'utilise-t-il pas simplement position: fixedsur le panneau?".

Veuillez ne pas suggérer cela car j'ai d'autres raisons.


7
"Y a-t-il un meilleur moyen?" - autre que de laisser le navigateur se comporter normalement?
Fenton

22
"mélodramatiquement"?
Mike Weller

6
Peut-être signifié par programme? Puisqu'il s'agit de la meilleure suggestion de correction orthographique de Firefox pour `` par programme ''
Michael Shimmins

4
Ce fil de discussion va \ b \
Cipi

3
@Sohnee désactivant le défilement! == bad
Mansiemans

Réponses:


136

Le seul moyen que j'ai trouvé pour le faire est similaire à ce que vous avez décrit:

  1. Prenez la position de défilement actuelle (n'oubliez pas l'axe horizontal!).
  2. Définissez le dépassement sur masqué (vous souhaitez probablement conserver la valeur de dépassement précédente).
  3. Faites défiler le document jusqu'à la position de défilement enregistrée avec scrollTo ().

Ensuite, lorsque vous êtes prêt à autoriser à nouveau le défilement, annulez tout cela.

Edit: aucune raison pour laquelle je ne peux pas vous donner le code puisque je me suis donné la peine de le déterrer ...

// lock scroll position, but retain settings for later
var scrollPosition = [
  self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
  self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var html = jQuery('html'); // it would make more sense to apply this to body, but IE7 won't have that
html.data('scroll-position', scrollPosition);
html.data('previous-overflow', html.css('overflow'));
html.css('overflow', 'hidden');
window.scrollTo(scrollPosition[0], scrollPosition[1]);


// un-lock scroll position
var html = jQuery('html');
var scrollPosition = html.data('scroll-position');
html.css('overflow', html.data('previous-overflow'));
window.scrollTo(scrollPosition[0], scrollPosition[1])

2
s'il vous plaît voir jsbin.com/ikuma4/2/edit et expliquez-moi une raison pour laquelle le vôtre est meilleur? est-ce que je manque quelque chose (je demande car je ne vois aucune raison de la longueur de votre réponse par rapport à mon exemple)
Hailwood

3
Votre approche ne fonctionne pas dans IE7. J'ai essayé cela en premier aussi. Le problème est qu'il ne réagit pas assez rapidement à l'événement de défilement. Il laisse le document défiler, puis le réenclenche lorsque votre JS réinitialise la position de défilement à l'endroit où vous le souhaitez.
tfe

1
De plus, si le corps avait un débordement autre que auto, il serait écrasé. J'avais besoin de préserver le paramètre existant, ce qui ajoute également des frais généraux.
tfe

Est-ce que quelqu'un sait pourquoi le style simple htmlet bodyavec overflow: hiddenest insuffisant? Nous finissons toujours par avoir besoin du gestionnaire d'événements.
kpozin

4
C'est une réponse fantastique. Et pour le faire fonctionner sur les appareils tactiles, consultez cette réponse.
Patrick

235

Cela désactivera complètement le défilement:

$('html, body').css({
    overflow: 'hidden',
    height: '100%'
});

Restaurer:

$('html, body').css({
    overflow: 'auto',
    height: 'auto'
});

Je l'ai testé sur Firefox et Chrome.


18
fonctionne comme prévu. Merci! Cela aurait dû être la réponse acceptée!
Dave Chen

6
Défile toujours avec le bouton central de la souris sur chrome.
Lothar

16
Cela perd la position de défilement actuelle. OP a explicitement mentionné la capture de la position du défilement, donc je suppose qu'il en avait besoin. Quoi qu'il en soit, j'en ai besoin, donc c'est d'une utilité limitée pour moi
zerm

7
PS L'omission du height: 100%verrouille efficacement le défilement à la position actuelle sans sauter - sur le dernier Chrome, au moins.
zerm du

2
Ce n'est PAS la bonne réponse. La position de défilement n'est pas capturée
taylorcressy

43

essaye ça

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})

exactement ce que je cherchais ... presque. Quoi qu'il en soit pour le désactiver pendant les touches fléchées?
Cody

2
@Cody - combinez cela avec le débordement CSS: caché
Darius.V

2
@cubbiu comment l'inverser?
Meer

3
Vous pouvez utiliser$('#element').off('scroll touchmove mousewheel');
arnuschky

1
Excellente solution. Bien que comment désactiveriez body- vous uniquement le défilement tout en autorisant le défilement dans d'autres éléments enfants qui l'ont fait overflow: scroll?
Fizzix

27

Je viens de fournir un petit réglage de la solution par tfe . En particulier, j'ai ajouté un contrôle supplémentaire pour m'assurer qu'il n'y a pas de décalage du contenu de la page (aka décalage de page ) lorsque la barre de défilement est définie sur hidden.

Deux fonctions Javascript lockScroll()et unlockScroll()peuvent être définies, respectivement, pour verrouiller et déverrouiller le défilement de la page.

function lockScroll(){
    $html = $('html'); 
    $body = $('body'); 
    var initWidth = $body.outerWidth();
    var initHeight = $body.outerHeight();

    var scrollPosition = [
        self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
        self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
    ];
    $html.data('scroll-position', scrollPosition);
    $html.data('previous-overflow', $html.css('overflow'));
    $html.css('overflow', 'hidden');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);   

    var marginR = $body.outerWidth()-initWidth;
    var marginB = $body.outerHeight()-initHeight; 
    $body.css({'margin-right': marginR,'margin-bottom': marginB});
} 

function unlockScroll(){
    $html = $('html');
    $body = $('body');
    $html.css('overflow', $html.data('previous-overflow'));
    var scrollPosition = $html.data('scroll-position');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);    

    $body.css({'margin-right': 0, 'margin-bottom': 0});
}

où j'ai supposé que le <body>n'a pas de marge initiale.

Notez que, bien que la solution ci-dessus fonctionne dans la plupart des cas pratiques, elle n'est pas définitive car elle nécessite une personnalisation supplémentaire pour les pages qui incluent, par exemple, un en-tête avec position:fixed. Entrons dans ce cas particulier avec un exemple. Supposons avoir

<body>
<div id="header">My fixedheader</div>
<!--- OTHER CONTENT -->
</body>

avec

#header{position:fixed; padding:0; margin:0; width:100%}

Ensuite, il faut ajouter les éléments suivants dans les fonctions lockScroll()et unlockScroll():

function lockScroll(){
    //Omissis   


    $('#header').css('margin-right', marginR);
} 

function unlockScroll(){
    //Omissis   

    $('#header').css('margin-right', 0);
}

Enfin, faites attention à une valeur initiale possible pour les marges ou les rembourrages.


4
Vous avez une erreur dans votre javascript $ body.css ({'margin-right': 0, 'margin-bottom', 0}); devrait être $ body.css ({'margin-right': 0, 'margin-bottom': 0});
Johansrk

En fait, il suffit d'utiliser marginRightet marginLeft:)
Martijn

25

vous pouvez utiliser ce code:

$("body").css("overflow", "hidden");

8
Vous pouvez toujours utiliser le bouton central de la souris pour faire défiler.
Roger Far

2
Non, c'est ok et pas de défilement avec ça!
mr.soroush

Si vous utilisez des css supplémentaires, vous POUVEZ désactiver complètement le défilement, voir ma réponse pour plus de détails.
gitaarik

21

Pour désactiver le défilement, essayez ceci:

var current = $(window).scrollTop();
$(window).scroll(function() {
    $(window).scrollTop(current);
});

réinitialiser:

$(window).off('scroll');

C'était une solution fantastique pour ce dont j'avais besoin.
Terry Carter

@EveryScreamer non, ça fait trembler l'écran comme un fou. Essayer de trouver une solution de contournement.
Telarian

5

J'ai écrit un plugin jQuery pour gérer cela: $ .disablescroll .

Il empêche le défilement des événements de la molette de la souris, du toucher et de la pression de touche, tels que Page Down.

Il y a une démo ici .

Usage:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");

J'ai essayé d'utiliser votre plugin disablescroll () pour désactiver temporairement le défilement en entendant l'événement mouswheel / scroll, mais cela ne fonctionne pas. Avez-vous une chance de connaître un moyen d'atteindre cet effet?
yellow-saint

@JB Je peux probablement vous aider, mais les commentaires ne sont pas le meilleur endroit. Rejoignez-moi dans ce chat de débordement de pile et je verrai ce que je peux faire: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Josh Harrison

Je suis désolé, mais ce plugin ne fonctionne même pas dans votre jsfiddle.
markj

Vous pouvez m'aider à inspecter cela en me disant dans quel navigateur / plate-forme il ne semble pas fonctionner s'il vous plaît?
Josh Harrison

5

Vous pouvez attacher une fonction pour faire défiler les événements et empêcher son comportement par défaut.

var $window = $(window);

$window.on("mousewheel DOMMouseScroll", onMouseWheel);

function onMouseWheel(e) {
    e.preventDefault();
}

https://jsfiddle.net/22cLw9em/


1
C'est la bonne réponse. Je ne sais pas pourquoi ce n'est pas réglé comme ça
Guilherme Ferreira

Ça marche. Juste besoin du code de réinitialisation posté pour correspondre à la réponse de Patrick
Hastig Zusammenstellen

4

Une doublure pour désactiver le défilement, y compris le bouton central de la souris.

$(document).scroll(function () { $(document).scrollTop(0); });

edit : Il n'y a pas besoin de jQuery de toute façon, ci-dessous comme ci-dessus dans vanilla JS (cela signifie pas de framework, juste JavaScript):

document.addEventListener('scroll', function () { this.documentElement.scrollTop = 0; this.body.scrollTop = 0; })

this.documentElement.scrollTop - standard

this.body.scrollTop - Compatibilité IE


4
  • Pour masquer le défilement: $("body").css("overflow", "hidden");
  • Pour restaurer le défilement: $("body").css("overflow", "initial");


3

Quelqu'un a posté ce code, qui a le problème de ne pas conserver la position de défilement lors de la restauration. La raison en est que les gens ont tendance à l'appliquer au html et au corps ou simplement au corps, mais il ne devrait être appliqué qu'au html. De cette façon, une fois restauré, la position de défilement sera conservée:

$('html').css({
    'overflow': 'hidden',
    'height': '100%'
});

Restaurer:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});

pas 'overflow': 'auto',utiliser'overflow': 'initial',
evtuhovdo

2

Cela peut ou non fonctionner pour vos besoins, mais vous pouvez étendre jScrollPane pour déclencher d'autres fonctionnalités avant qu'il ne fasse son défilement. Je viens juste de tester cela un peu, mais je peux confirmer que vous pouvez intervenir et empêcher complètement le défilement. Tout ce que j'ai fait c'est:

  • Téléchargez le zip de démonstration: http://github.com/vitch/jScrollPane/archives/master
  • Ouvrez la démo "Événements" (events.html)
  • Modifiez-le pour utiliser la source de script non minifiée: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • Dans jquery.jscrollpane.js, insérez un "return;" à la ligne 666 (numéro de ligne de bon augure! mais au cas où votre version diffère légèrement, c'est la première ligne de la positionDragY(destY, animate)fonction

Lancez events.html et vous verrez une boîte de défilement normalement qui en raison de votre intervention de codage ne défilera pas.

Vous pouvez contrôler l'ensemble des barres de défilement du navigateur de cette façon (voir fullpage_scroll.html).

Donc, probablement la prochaine étape est d'ajouter un appel à une autre fonction qui se déclenche et fait votre magie d'ancrage, puis décide de continuer avec le défilement ou non. Vous avez également des appels d'API pour définir scrollTop et scrollLeft.

Si vous voulez plus d'aide, postez où vous en êtes!

J'espère que cela a aidé.



1

Si vous souhaitez simplement désactiver le défilement avec la navigation au clavier, vous pouvez remplacer l'événement keydown.

$(document).on('keydown', function(e){
    e.preventDefault();
    e.stopPropagation();
});

1

Essayez ce code:

    $(function() { 
        // ...

        var $body = $(document);
        $body.bind('scroll', function() {
            if ($body.scrollLeft() !== 0) {
                $body.scrollLeft(0);
            }
        });

        // ...
    });

0

Vous pouvez couvrir la fenêtre avec un div à défilement pour empêcher le défilement du contenu sur une page. Et, en masquant et en affichant, vous pouvez verrouiller / déverrouiller votre parchemin.

Faites quelque chose comme ceci:

#scrollLock {
    width: 100%;
    height: 100%;
    position: fixed;
    overflow: scroll;
    opacity: 0;
    display:none
}

#scrollLock > div {
    height: 99999px;
}

function scrollLock(){
    $('#scrollLock').scrollTop('10000').show();
}

function scrollUnlock(){
    $('#scrollLock').hide();
}

7
Veuillez ne pas utiliser d'abréviations telles que «u» et «smth». Prenez le temps de bien épeler, pour plus de lisibilité.
le Tin Man du

0

Pour les personnes qui ont des mises en page centrées (via margin:0 auto;), voici un mash-up de la position:fixedsolution avec la solution proposée par @tfe .

Utilisez cette solution si vous rencontrez un accrochage de page (en raison de l'affichage / du masquage de la barre de défilement).

// lock scroll position, but retain settings for later
var scrollPosition = [
    window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
    window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var $html = $('html'); // bow to the demon known as MSIE(v7)
$html.addClass('modal-noscroll');
$html.data('scroll-position', scrollPosition);
$html.data('margin-top', $html.css('margin-top'));
$html.css('margin-top', -1 * scrollPosition[1]);

…combiné avec…

// un-lock scroll position
var $html = $('html').removeClass('modal-noscroll');
var scrollPosition = $html.data('scroll-position');
var marginTop = $html.data('margin-top');
$html.css('margin-top', marginTop);
window.scrollTo(scrollPosition[0], scrollPosition[1])

… Et enfin, le CSS pour .modal-noscroll

.modal-noscroll
{
    position: fixed;
    overflow-y: scroll;
    width: 100%;
}

Je me risquerais à dire est plus d'une solution appropriée que toutes les autres solutions là - bas, mais je ne l' ai pas testé ce encore bien ...: P


Edit: veuillez noter que je n'ai aucune idée de la façon dont cela pourrait fonctionner (lire: exploser) sur un appareil tactile.


0

Vous pouvez également utiliser DOM pour ce faire. Supposons que vous ayez une fonction que vous appelez comme ceci:

function disable_scroll() {
document.body.style.overflow="hidden";
}

Et c'est tout ce qu'il y a à faire! J'espère que cela aide en plus de toutes les autres réponses!


0

C'est ce que j'ai fini par faire:

CoffeeScript:

    $("input").focus ->
        $("html, body").css "overflow-y","hidden"
        $(document).on "scroll.stopped touchmove.stopped mousewheel.stopped", (event) ->
            event.preventDefault()

    $("input").blur ->
        $("html, body").css "overflow-y","auto"
        $(document).off "scroll.stopped touchmove.stopped mousewheel.stopped"

Javascript:

$("input").focus(function() {
 $("html, body").css("overflow-y", "hidden");
 $(document).on("scroll.stopped touchmove.stopped mousewheel.stopped", function(event) {
   return event.preventDefault();
 });
});

$("input").blur(function() {
 $("html, body").css("overflow-y", "auto");
 $(document).off("scroll.stopped touchmove.stopped mousewheel.stopped");
});

0

Je ne sais pas si quelqu'un a essayé ma solution. Celui-ci fonctionne sur tout le corps / html mais il ne fait aucun doute qu'il peut être appliqué à n'importe quel élément qui déclenche un événement de défilement.

Il suffit de définir et de désactiver scrollLock selon vos besoins.

var scrollLock = false;
var scrollMem = {left: 0, top: 0};

$(window).scroll(function(){
    if (scrollLock) {
        window.scrollTo(scrollMem.left, scrollMem.top);
    } else {
        scrollMem = {
            left: self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
            top: self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        };
    }
});

Voici l'exemple JSFiddle

J'espère que celui-ci aide quelqu'un.


Celui-ci fonctionne comme il se doit, à une exception près. Quand le parchemin est verrouillé, et que je fais défiler, ça bouge un peu, avant de verrouiller le parchemin ...
Thomas Teilmann

0

Je pense que la solution la meilleure et la plus propre est:

window.addEventListener('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y);
});

Et avec jQuery:

$(window).on('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y)
})

Ces écouteurs d'événements devraient bloquer le défilement. Supprimez-les simplement pour réactiver le défilement

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.