js/css: deshabilite la barra de desplazamiento pero mantenga la posición de desplazamiento

10 minutos de lectura

Estoy usando el cuadro de diálogo Jquery para abrir una ventana de cuadro emergente en la parte superior de una página. Cuando abro el cuadro de diálogo, quiero que se deshabilite el desplazamiento general de la página. Para hacerlo, estoy haciendo:

$('body').css({overflow:'hidden'});

cuando se abre el cuadro de diálogo, y:

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

cuando se cierra el cuadro de diálogo.

Esto funciona, pero cuando se elimina la barra de desplazamiento, el contenido de la parte posterior se mueve hacia la derecha y el resultado no es agradable.

Probé otro método, creando una clase css “noscroll”, como tal:

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

luego, en lugar del código js anterior, agrego y elimino esta clase en el cuerpo al abrir/cerrar el cuadro de diálogo.

Ahora bien, esto funciona para la barra de desplazamiento y el contenido en la parte posterior no se mueve hacia la derecha, pero con este método, el contenido en la parte posterior vuelve a la parte superior.

Básicamente, el método 1 hace que el contenido se mueva hacia la derecha y el método 2 hace que el contenido vuelva a la parte superior.

¿Alguien sabe una solución para esto? no hay desplazamiento para el contenido en la parte posterior cuando se abre el cuadro de diálogo, y no hay movimiento al desactivar el desplazamiento…?

  • ¿Ha considerado implementar una superposición de div del 100 % en posición absoluta detrás del cuadro de diálogo para bloquear todas las interacciones con la página?

    – dcuadrado

    3 sep 2012 a las 20:52


  • ¡Bien pensado, lo intentaré y publicaré mis resultados!

    – Pedro

    3 de septiembre de 2012 a las 21:06

  • ¿Encontraste la solución para esta pregunta? ¿me puedes ayudar? ¡Gracias! Lo siento, no hablo bien el inglés.

    – Thanh Nguyen

    21 de abril de 2013 a las 18:20

  • Realmente no, prueba lo que usé y lo que sugirió la gente, y mira qué funciona mejor para ti…

    – Pedro

    22 de abril de 2013 a las 8:09

Avatar de usuario de Karl-André Gagnon
Karl André Gagnon

He hecho un ejemplo bastante simple de mi solución.

http://jsfiddle.net/6eyJm/1/

Su ventana emergente debe estar en un cuadro

<div id="shadow">
<div id="popup">
    <a id='close' href="#">Close</a>
</div>

Luego pon esos CSS en el root div

#shadow{
    display: none;
    position: fixed;
    top:0;
    bottom: 0;
    width: 100%;
    height:100%;
    background-color: rgba(0,0,0,0.6);
}

La posición fija es realmente importante ya que no desea ver el borde blanco, ocupará todo el ancho de la ventana y no el cuerpo.

Luego está el pequeño truco de JS

$('#open').click(function(e){
    e.preventDefault()
    $('body').width($('body').width());
    $('body').css('overflow', 'hidden');
    $('#shadow').css('display', 'block');
})
$('#close').click(function(e){
    e.preventDefault()
    $('body, #shadow').removeAttr('style')
})

El objetivo aquí es tomar el ancho del cuerpo antes de quitar la barra de desplazamiento. Su contenido no se moverá.

¡Espero que ayude!

Lo siento por mi inglés, no mi idioma nativo.

  • Hice un pequeño error tipográfico, no debería ser $(‘body #shadow’).removeAttr sino $(‘body, #shadow’).removeAttr (falta la coma).

    – Karl-André Gagnon

    29 de abril de 2013 a las 14:20

  • cuando coloco el botón Abrir en el medio de la lista, luego hago clic, el desplazamiento de la página está deshabilitado pero vuelve a la parte superior.

    – Thanh Nguyen

    29 de abril de 2013 a las 16:10

  • sigue sin funcionar. cuando está abierto, la posición de desplazamiento se mantiene allí, pero cuando está cerrado, vuelve a la parte superior. Mi código aquí: http://jsfiddle.net/ZG8FU/

    – Thanh Nguyen

    29 de abril de 2013 a las 16:24


  • @TheatreOfSouls El enlace de anclaje se desplaza a la página hasta la parte superior. Evite el comportamiento predeterminado del enlace: jsfiddle.net/zujv0g36.

    – Karl-André Gagnon

    12 de agosto de 2019 a las 12:51


  • La publicación de hace 7 años me salvó el día 🙂 Muchas gracias por la idea, funciona de maravilla y, sinceramente, no veo el problema con tu inglés: D

    –Emil Borconi

    10 de marzo de 2020 a las 20:09

Recordar el desplazamiento debería mantener tu ventana emergente a raya;

JSfiddle

HTML

<div id="popupholder">
    <button id="close">Close me</button>
</div>


asd <br />asd <br />asd <br />asd <br />asd <br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
<button class="open">Popup</button>
<br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />

CSS

html, body {
    margin: 0px;
}

#popupholder {
    width: 100%;
    height: 100%;
    position: absolute;
    display: box;
    display: -webkit-box;
    display: -moz-box;
    background-color: rgba(0,0,0,0.75);
    display: none;
}

#close {
    display: block;
    height: 20px;
    margin: 75px auto 0px auto;
}

JavaScript

$(document).ready(function() {
    $('.open').click(function() {
        // Block scrolling
        $('body').css('overflow', 'hidden');

        // Show popup
        var offset = window.pageYOffset;
        //console.log(offset);
        $('#popupholder').css({
            'display': 'block',
            'top': offset + 'px'
        });
    });

    $('#close').click(function() {
        // Enable scrolling
        $('body').css('overflow', 'auto');

        // Hide popup
        $('#popupholder').css('display', 'none');
    });
});

Por razones de seguridad, podría agregar un valor muy alto z-index para usted #popupholderpero eso no es realmente relevante para la pregunta.

  • Gracias por tomarse el tiempo para escribir el código, pero quiero deshabilitar la barra de desplazamiento, no ocultarla como la ventana emergente de Facebook.

    – Thanh Nguyen

    22 de abril de 2013 a las 11:06

  • Puedes añadir overflow: hidden; hacia #popupholder también. De lo contrario, puede buscar variantes similares de WebKit ::-webkit-scrollbar { display: none; } estilismo Accederá a la Sombra DOM y ocultar la barra de desplazamiento por completo.

    usuario1467267

    22 de abril de 2013 a las 16:40

Tuve el mismo problema, este repositorio me ayudó. sin desplazamiento

Avatar de usuario del arquitecto
Arquitecto

Esta es la mejor solución que tengo hasta ahora. Y créanme, probé todos los demás y esta es la mejor y más simple solución que se me ocurrió. funciona muy bien en dispositivos Windowsque empuja la página desde la derecha para tener espacio para la barra de desplazamiento del sistema y dispositivos iOS que no requieren espacio para sus barras de desplazamiento en los navegadores. Entonces, al usar esto, no necesitará agregar relleno a la derecha para que la página no parpadee cuando ocultar el desbordamiento del cuerpo o html con css.

La solución es bastante simple si lo piensas. La idea es darle la ventana.scrollTop() la misma posición exacta en el momento en que se abre una ventana emergente. También cambie esa posición cuando la ventana cambie de tamaño (ya que la posición de desplazamiento cambia una vez que eso sucede).

Así que, aquí vamos…

Primero, creemos la variable que le permitirá saber que la ventana emergente está abierta y llámela detenerVentanaScroll. Si no hacemos esto, obtendrá un error de una variable indefinida en su página y la establecerá en 0, como no activa.

$(document).ready(function(){
    stopWindowScroll = 0;
});

Ahora hagamos que la función de ventana emergente abierta pueda ser cualquier función en su código que active cualquier ventana emergente que esté usando como complemento o personalizado. En este caso, será una simple ventana emergente personalizada con un documento simple al hacer clic en la función.

$(document).on('click','.open-popup', function(){
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
});

Entonces, lo siguiente que hacemos es crear la función de cerrar ventana emergente, que repito nuevamente puede ser cualquier función que ya haya creado o esté usando en un complemento. Lo importante es que necesitamos esas 2 funciones para configurar el detenerVentanaScroll variable a 1 o 0 para saber cuándo está abierto o cerrado.

$(document).on('click','.open-popup', function(){
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
});

Entonces vamos a crear la función window.scroll para que podamos evitar el desplazamiento una vez que el detenerVentanaScroll mencionado anteriormente se establece en 1 – como activo.

$(window).scroll(function(){
    if(stopWindowScroll == 1) {
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    }
});

Eso es todo. No se requiere CSS para que esto funcione, excepto sus propios estilos para la página. Esto funcionó de maravilla para mí y espero que te ayude a ti y a otros.

Aquí hay un ejemplo de trabajo en JSFiddle:

Ejemplo de violín JS

Hagame saber si esto fue de utilidad. Saludos.

avatar de usuario de ale
cerveza inglesa

puede calcular la diferencia entre el ancho del cuerpo, antes y después del desbordamiento oculto, y aplicarlo como relleno derecho al cuerpo

var bodyStartW = $("body").width();
$("body").css("overflow-y" , "hidden");
var bodyEndW = $("body").width();
var bodyMarginL = bodyEndW - bodyStartW;
$("body").css("padding-right" , bodyMarginL);

En Safari tenías el mismo truco para la etiqueta “html” y margin-right en lugar de padding-right

Avatar de usuario de Igor Adamenko
Ígor Adamenko

Yo uso estas dos funciones para el mismo propósito:

function enableBodyScroll() {
  if (document.readyState === 'complete') {
    document.body.style.position = '';
    document.body.style.overflowY = '';

    if (document.body.style.marginTop) {
      const scrollTop = -parseInt(document.body.style.marginTop, 10);
      document.body.style.marginTop = '';
      window.scrollTo(window.pageXOffset, scrollTop);
    }
  } else {
    window.addEventListener('load', enableBodyScroll);
  }
}

function disableBodyScroll({ savePosition = false } = {}) {
  if (document.readyState === 'complete') {
    if (document.body.scrollHeight > window.innerHeight) {
      if (savePosition) document.body.style.marginTop = `-${window.pageYOffset}px`;
      document.body.style.position = 'fixed';
      document.body.style.overflowY = 'scroll';
    }
  } else {
    window.addEventListener('load', () => disableBodyScroll({ savePosition }));
  }
}

Cómo funciona:

  1. Cuando desee deshabilitar el desplazamiento para guardar la posición actual, ejecute disableBodyScroll({ savePosition: true }).

  2. La función verifica si la página se cargó o no (porque el usuario puede activar la apertura del cuadro de diálogo durante la carga).

  3. Si la página está cargada, guarda la posición de desplazamiento actual configurando margin-top en bodyentonces se establece position: fixed; overflow-y: scroll en él para eliminar la barra de desplazamiento.

  4. Si la página no está cargada, agrega un detector de eventos para ejecutar (3.) cuando se carga la página.

Para habilitar el desplazamiento, todo es igual, pero la función elimina estilos en lugar de configurarlos.

Fuente del código: https://github.com/funbox/diamonds/blob/master/lib/body-scroll.ts

¿Ha sido útil esta solución?