Cómo deshabilitar mediante programación el desplazamiento de página con jQuery

163

Usando jQuery, me gustaría deshabilitar el desplazamiento del cuerpo:

Mi idea es:

  1. Conjunto body{ overflow: hidden;}
  2. Captura la corriente scrollTop();/scrollLeft()
  3. Enlace al evento de desplazamiento del cuerpo, establezca scrollTop / scrollLeft en el valor capturado.

¿Hay una mejor manera?


Actualizar:

Vea mi ejemplo y una razón por la cual, en http://jsbin.com/ikuma4/2/edit

Soy consciente de que alguien estará pensando "¿por qué no solo lo usa position: fixeden el panel?".

Por favor no sugiera esto ya que tengo otras razones.

Granizo
fuente
77
"¿Hay una mejor manera?" - aparte de dejar que el navegador se comporte normalmente?
Fenton
22
"melodramáticamente"?
Mike Weller
66
¿Quizás quiso decir programáticamente? Ya que es la sugerencia de corrección ortográfica superior de
Firefox
44
Este hilo va \ b \
Cipi
3
@Sohnee deshabilita el desplazamiento! == malo
Mansiemans

Respuestas:

136

La única forma en que he encontrado para hacer esto es similar a lo que describiste:

  1. Tome la posición de desplazamiento actual (¡no olvide el eje horizontal!).
  2. Establezca el desbordamiento en oculto (probablemente desee retener el valor de desbordamiento anterior).
  3. Desplace el documento a la posición de desplazamiento almacenada con scrollTo ().

Luego, cuando esté listo para permitir el desplazamiento nuevamente, deshaga todo eso.

Editar: no hay razón para que no pueda darte el código ya que me tomé la molestia de desenterrarlo ...

// 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])
tfe
fuente
2
por favor vea jsbin.com/ikuma4/2/edit y explíqueme alguna razón para que la suya sea mejor. Me estoy perdiendo algo (i pregunto ya que no puedo ver ninguna razón por la duración de su respuesta en comparación con mi ejemplo)
Hailwood
3
Su enfoque no funciona en IE7. Intenté eso primero también. El problema es que no reacciona al evento de desplazamiento lo suficientemente rápido. Permite que el documento se desplace, luego lo vuelve a ajustar cuando su JS restablece la posición de desplazamiento donde lo desea.
tfe
1
Además, si el cuerpo tuviera un desbordamiento de otra cosa que no sea auto, se sobrescribirá. Necesitaba preservar la configuración existente, por lo que también agrega algo de sobrecarga.
tfe
¿Alguien sabe por qué simplemente el estilo htmly bodycon overflow: hiddenes insuficiente? Todavía terminamos necesitando el controlador de eventos.
kpozin
44
Esta es una respuesta fantástica. Y para que funcione en dispositivos táctiles, mira esta respuesta.
Patrick
235

Esto deshabilitará completamente el desplazamiento:

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

Restaurar:

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

Probado en Firefox y Chrome.

gitaarik
fuente
18
Funciona como se esperaba. ¡Gracias! ¡Esta debería haber sido la respuesta aceptada!
Dave Chen
66
Todavía se desplaza con el botón central del mouse en cromo.
Lothar
16
Esto pierde la posición actual de desplazamiento. OP mencionó explícitamente sobre la captura de la posición de desplazamiento, por lo que supongo que lo necesitaba. De todas formas, yo lo requieran, por lo que este es de uso limitado para mí
zerm
77
PS Omitir height: 100%bloquea efectivamente el desplazamiento en la posición actual sin saltar, al menos en el último Chrome.
zerm
2
Esta NO es la respuesta correcta. La posición de desplazamiento no se captura
taylorcressy
43

prueba esto

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})
cubbiu
fuente
justo lo que estaba buscando ... casi. De todos modos para deshabilitarlo durante las teclas de flecha?
Cody
2
@Cody: combine esto con el desbordamiento de CSS: oculto
Darius.V
2
@cubbiu ¿cómo revertirlo?
Meer
3
Puede usar$('#element').off('scroll touchmove mousewheel');
arnuschky
1
Gran solución Aunque, ¿cómo deshabilitaría el bodydesplazamiento y permitiría el desplazamiento dentro de otros elementos secundarios que tienen overflow: scroll?
Fizzix
27

Solo proporciono un pequeño ajuste a la solución por tfe . En particular, agregué un control adicional para garantizar que no haya cambios en el contenido de la página (también conocido como cambio de página ) cuando la barra de desplazamiento está configurada en hidden.

Dos funciones Javascript lockScroll()y unlockScroll()se pueden definir, respectivamente, para bloquear y desbloquear el desplazamiento de la página.

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

donde supuse que <body>no tiene margen inicial.

Tenga en cuenta que, si bien la solución anterior funciona en la mayoría de los casos prácticos, no es definitiva, ya que necesita más personalización para las páginas que incluyen, por ejemplo, un encabezado con position:fixed. Veamos este caso especial con un ejemplo. Supongamos tener

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

con

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

Entonces, uno debe agregar lo siguiente en funciones lockScroll()y unlockScroll():

function lockScroll(){
    //Omissis   


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

function unlockScroll(){
    //Omissis   

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

Finalmente, tenga en cuenta algunos posibles valores iniciales para los márgenes o rellenos.

JeanValjean
fuente
44
Tiene un error en su javascript $ body.css ({'margin-right': 0, 'margin-bottom', 0}); debe ser $ body.css ({'margin-right': 0, 'margin-bottom': 0});
Johansrk
En realidad, solo use marginRighty marginLeft:)
Martijn
25

puedes usar este código:

$("body").css("overflow", "hidden");
Sr. soroush
fuente
8
Todavía puede usar el botón central del mouse para desplazarse.
Roger Far
2
No, esto está bien y no hay desplazamiento con esto!
Sr. soroush
Si usa un CSS adicional, PUEDE desactivar completamente el desplazamiento, consulte mi respuesta para obtener más detalles.
gitaarik
21

Para desactivar el desplazamiento, intente esto:

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

reiniciar:

$(window).off('scroll');
Patrick DaVader
fuente
Esta fue una solución fantástica para lo que necesitaba.
Terry Carter el
@EveryScreamer no, hace que la pantalla tiemble como loca. Intentando encontrar una solución.
Telarian
5

He escrito un complemento jQuery para manejar esto: $ .disablescroll .

Impide el desplazamiento desde la rueda del mouse, el movimiento táctil y los eventos de pulsación de teclas, como Page Down.

Hay una demostración aquí .

Uso:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");
Josh Harrison
fuente
Intenté usar su complemento disablescroll () para deshabilitar temporalmente el desplazamiento al escuchar el evento mouswheel / scroll, pero no funciona. ¿Alguna posibilidad de que conozcas una forma de lograr ese efecto?
amarillo-santo
@JB Probablemente pueda ayudar, pero los comentarios no son el mejor lugar. Únase a mí en este chat de desbordamiento de pila y veré lo que puedo hacer: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Josh Harrison
Lo siento, pero este complemento ni siquiera funciona en tu jsfiddle.
markj
¿Puede ayudarme a inspeccionar esto diciéndome en qué navegador / plataforma no parece funcionar, por favor?
Josh Harrison el
5

Puede adjuntar una función para desplazar eventos y evitar su comportamiento predeterminado.

var $window = $(window);

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

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

https://jsfiddle.net/22cLw9em/

dzimi
fuente
1
Esta es la respuesta correcta. No sé por qué no está configurado como tal
Guilherme Ferreira
Funciona. Solo necesita que se publique el código de restablecimiento para que coincida con la respuesta de Patricks
Hastig Zusammenstellen
4

Un revestimiento para deshabilitar el desplazamiento, incluido el botón central del mouse.

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

editar : no hay necesidad de jQuery de todos modos, debajo de lo mismo que arriba en vanilla JS (eso significa que no hay marcos, solo JavaScript):

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

this.documentElement.scrollTop - estándar

this.body.scrollTop: compatibilidad con IE

Pawel
fuente
4
  • Para ocultar el desplazamiento: $("body").css("overflow", "hidden");
  • Para restaurar el desplazamiento: $("body").css("overflow", "initial");
Joan Alberto Aguilar Peña
fuente
3

¿No puede simplemente establecer la altura del cuerpo al 100% y el desbordamiento oculto? Ver http://jsbin.com/ikuma4/13/edit

Adrian Schmidt
fuente
$ ("html"). css ({altura: '100%', desbordamiento: 'oculto'}); Simplemente funciona, gracias Adrian
Alexey
3

Alguien publicó este código, que tiene el problema de no retener la posición de desplazamiento cuando se restaura. La razón es que las personas tienden a aplicarlo a html y al cuerpo o solo al cuerpo, pero debe aplicarse solo a html. De esta manera, cuando se restaure, se mantendrá la posición de desplazamiento:

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

Restaurar:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});
Mescalina
fuente
no 'overflow': 'auto',uso'overflow': 'initial',
evtuhovdo
2

Esto puede o no funcionar para sus propósitos, pero puede extender jScrollPane para activar otra funcionalidad antes de que se desplace. Acabo de probar esto un poco, pero puedo confirmar que puedes saltar y evitar el desplazamiento por completo. Todo lo que hice fue:

  • Descargue el zip de demostración: http://github.com/vitch/jScrollPane/archives/master
  • Abra la demostración "Eventos" (events.html)
  • Edítelo para usar la fuente de script no minificada: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • Dentro de jquery.jscrollpane.js, inserte un "retorno"; en la línea 666 (¡número de línea auspicioso! pero en caso de que su versión difiera ligeramente, esta es la primera línea de la positionDragY(destY, animate)función

Encienda events.html, y verá un cuadro de desplazamiento normal que debido a su intervención de codificación no se desplazará.

Puede controlar todas las barras de desplazamiento del navegador de esta manera (consulte fullpage_scroll.html).

Entonces, presumiblemente, el siguiente paso es agregar una llamada a alguna otra función que se active y haga su magia de anclaje, luego decida si continuar con el desplazamiento o no. También tienes llamadas API para configurar scrollTop y scrollLeft.

Si desea más ayuda, ¡publique donde llegue!

Espero que esto haya ayudado.

Jeremy Warne
fuente
1

Si solo desea deshabilitar el desplazamiento con la navegación del teclado, puede anular el evento keydown.

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

Prueba este código:

    $(function() { 
        // ...

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

        // ...
    });
Joder
fuente
0

Puede ocultar la ventana con un div desplazable para evitar el desplazamiento del contenido en una página. Y, al ocultar y mostrar, puede bloquear / desbloquear su desplazamiento.

Haz algo como esto:

#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();
}
Appex
fuente
77
No utilice abreviaturas como "u" y "smth". Tómese el tiempo para deletrear correctamente, para facilitar la lectura.
The Tin Man
0

Para las personas que tienen diseños centrados (vía margin:0 auto;), aquí hay una combinación de la position:fixedsolución junto con la solución propuesta de @tfe .

Use esta solución si está experimentando un ajuste de página (debido a que la barra de desplazamiento muestra / oculta).

// 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]);

…combinado con…

// 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])

... y finalmente, el CSS para .modal-noscroll...

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

Me atrevería a decir que esto es más de una solución adecuada que cualquiera de las otras soluciones por ahí, pero yo no lo he probado que a fondo todavía ...: P


Editar: tenga en cuenta que no tengo idea de lo mal que esto podría funcionar (léase: explotar) en un dispositivo táctil.

Matthemattics
fuente
0

También puede usar DOM para hacerlo. Digamos que tiene una función que llama así:

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

¡Y eso es todo! Espero que esto ayude, además de todas las otras respuestas.

Brendan
fuente
0

Esto es lo que terminé haciendo:

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");
});
Marz
fuente
0

No estoy seguro si alguien ha probado mi solución. Este funciona en todo el cuerpo / html, pero sin duda se puede aplicar a cualquier elemento que active un evento de desplazamiento.

Simplemente active y desactive scrollLock según lo necesite.

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

Aquí está el ejemplo JSFiddle

Espero que esto ayude a alguien.

FossilMFC
fuente
Éste funciona como debería, con una excepción. Cuando el pergamino está bloqueado, y yo me desplazo, se retuerce un poco, antes de realmente bloquear el pergamino ...
Thomas Teilmann
0

Creo que la mejor y limpia solución es:

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

Y con jQuery:

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

Esos oyentes de eventos deberían bloquear el desplazamiento. Simplemente quítelos para volver a habilitar el desplazamiento

Tiziano
fuente