¿Cómo evitar que la barra de desplazamiento reposicione la página web?

218

Tengo un sitio web con DIV alineado al centro. Ahora, algunas páginas necesitan desplazarse, otras no. Cuando me muevo de un tipo a otro, la apariencia de una barra de desplazamiento mueve la página unos pocos píxeles hacia un lado. ¿Hay alguna forma de evitar esto sin mostrar explícitamente las barras de desplazamiento en cada página?

Dmitri Nesteruk
fuente
66
¿Por qué nadie menciona overflow-y: overlayen este hilo?
milkersarac
3
De acuerdo con los documentos de overflow-y: overlay
Mozilla

Respuestas:

266

overflow-y: scroll es correcto, pero debe usarlo con la etiqueta html, no body o de lo contrario obtendrá una barra de desplazamiento doble en IE 7
Entonces el CSS correcto sería:

html {
  overflow-y: scroll;
}
Rubén
fuente
1
IE 10+ tiene una barra de desplazamiento flotante, por lo que debe desactivar esto para estos navegadores
Ruben
1
esto puede causar problemas como barras de desplazamiento dobles cuando se usa en combinación con fancybox o twitter bootstrap modal
Ruben
información adicional: twitter bootstrap ahora agrega .modal-open a tu cuerpo cuando un modal está abierto
Ruben
55
Vale la pena mencionar que esto muestra permanentemente una barra de desplazamiento vertical. Puede que no siempre sea aceptable.
rustyx
Obtengo una barra de desplazamiento doble en Chromium y Firefox. Estoy usando flex-box; tal vez eso esté causando esto ...
Garrett
72

Envuelva el contenido de su elemento desplazable en un div y aplique padding-left: calc(100vw - 100%);.

<body>
    <div style="padding-left: calc(100vw - 100%);">
        Some Content that is higher than the user's screen
    </div>
</body>

El truco es que 100vwrepresenta el 100% de la ventana gráfica, incluida la barra de desplazamiento. Si resta 100%, que es el espacio disponible sin la barra de desplazamiento, terminará con el ancho de la barra de desplazamiento o 0si no está presente. Crear un relleno de ese ancho a la izquierda simulará una segunda barra de desplazamiento, desplazando el contenido centrado de nuevo a la derecha.

Tenga en cuenta que esto solo funcionará si el elemento desplazable usa todo el ancho de la página, pero esto no debería ser un problema la mayor parte del tiempo porque solo hay algunos otros casos en los que ha centrado el contenido desplazable.

Rapti
fuente
1
Se aplicaría mejor a través de una clase que un estilo en línea, y solo funcionará en estos navegadores , pero esta es una técnica inteligente: no me había dado cuenta de eso 100vwy 100%medí cosas diferentes, ¡así que aprendí algo útil de esto!
Nick F
21
Esto es absolutamente genial y es realmente la mejor respuesta teniendo en cuenta que el soporte del navegador para calc es muy bueno.
michael
1
Puede hacer lo mismo, excepto que en lugar de agregar un margen a la izquierda, agrega un margen negativo a la derecha (consulte stackoverflow.com/a/39289453/6015444 ).
Touniouk
2
Esta solución causará problemas similares con el color de fondo, como la respuesta "ancho: calc (100vw - 34px);" Pero en el lado izquierdo.
Maciej Lew
1
Recomendaría agregar algunas consultas de medios a este estilo @media screen and (min-width: 800px) {...} . En los casos en que el contenido se ajuste al ancho de la página. Por ejemplo, en resoluciones pequeñas, habrá una brecha innecesaria, desplazando el contenido a la derecha
MarkosyanArtur
44

Yo creo que no. Pero el estilo bodycon overflow: scrolldebería hacerlo. Aunque pareces saber eso.

Michael Krelin - hacker
fuente
3
Suena bien ... obliga a la página a mostrar siempre la barra de desplazamiento, ya sea que la necesite o no, ... entonces no hay cambio visual entre los tipos de página.
eidylon
1
Sí, pero IIRC, esto muestra ambas barras de desplazamiento. Realmente no necesito el horizontal.
Dmitri Nesteruk
Es verdad. Pero no hay mucho que pueda hacer para ayudarlo :( En realidad, solo considero que la primera oración de mi respuesta es la respuesta real que se ocupa de la pregunta.
Michael Krelin - hacker
49
overflow-y: scroll:)
Svish
2
La siguiente es la mejor respuesta
Sami
36

Con el desplazamiento siempre mostrado, quizás no sea bueno para el diseño.

Intenta limitar el ancho del cuerpo con css3

body {
    width: calc(100vw - 34px);
}

vwes el ancho de la ventana gráfica (vea este enlace para obtener una explicación)
calccalcular en css3
34pxsignifica ancho de barra de desplazamiento doble (vea esto para fijo o esto para calcular si no confía en tamaños fijos)

Moesio
fuente
44
Todo es inútil hasta que alguien lo necesite.
Moesio
3
Esto es visualmente mucho menos intrusivo que simplemente forzar barras de desplazamiento como se describe en la respuesta aceptada.
Silas Hansen
44
Esto ha funcionado mejor para mis necesidades hasta ahora, también agregué padding-left: 34px;para centrar uniformemente mi página.
Pat Migliaccio
3
Esta debería ser la respuesta aceptada, a diferencia de la actualmente aceptada, ¡en realidad está respondiendo la pregunta!
Porque el
2
Esto causará problemas si tiene una barra de navegación / encabezado con un color diferente que el fondo del cuerpo o el borde inferior, etc.
Zia Ul Rehman Mughal
28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

Ejemplo . Haga clic en el botón "Cambiar altura mínima".

Con calc(100vw - 100%)podemos calcular el ancho de la barra de desplazamiento (y si no se muestra, será 0). Idea: usando el margen negativo a la derecha, podemos aumentar el ancho de <html>este ancho. Verá una barra de desplazamiento horizontal; debe ocultarse usando overflow-x: hidden.

pongo
fuente
Tuve que poner el cuerpo en un div y aplicar el margen al div para que funcione (similar a la respuesta de Rapti ). Pero esto se ve mucho más ordenado.
Touniouk
1
Esto funciona muy bien y no parece tener como resultado barras de desplazamiento horizontales no deseadas en Chrome o Firefox. ¿Por qué no solo usar en calc(100% - 100vw)lugar de multiplicar por -1?
SystemParadox
13

No sé si esta es una publicación anterior, pero tuve el mismo problema y si quieres desplazarte verticalmente solo debes intentarlo overflow-y:scroll


fuente
13

Si cambia el tamaño o después de cargar algunos datos, está agregando la barra de desplazamiento, puede intentar lo siguiente, crear una clase y aplicar esta clase.

.auto-scroll {
   overflow-y: overlay;
   overflow-x: overlay;
}
kunalkamble
fuente
3

He resuelto el problema en uno de mis sitios web estableciendo explícitamente el ancho del cuerpo en javascript por el tamaño de la vista menos el ancho de la barra de desplazamiento. Utilizo una función basada en jQuery documentada aquí para determinar el ancho de la barra de desplazamiento.

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Frank L
fuente
10
Ni siquiera puedo comenzar a explicar por qué es una práctica tan mala.
mythofechelon
20
@BenHooper: Me gustaría saber por qué esta es una mala práctica.
Saad
1
¿Qué sucede si cambia el tamaño de la ventana?
Braden Steffaniak
3

Ampliando la respuesta usando esto:

body {
    width: calc(100vw - 17px);
}

Un comentarista sugirió agregar también el relleno izquierdo para mantener el centrado:

body {
    padding-left: 17px;
    width: calc(100vw - 17px);
}

Pero las cosas no parecen correctas si su contenido es más ancho que la ventana gráfica. Para solucionarlo, puede usar consultas de medios, como esta:

@media screen and (min-width: 1058px) {
    body {
        padding-left: 17px;
        width: calc(100vw - 17px);
    }
}

Donde el 1058px = ancho de contenido + 17 * 2

Esto permite que una barra de desplazamiento horizontal maneje el desbordamiento xy mantenga centrado el contenido centrado cuando la ventana gráfica es lo suficientemente amplia como para contener su contenido de ancho fijo

Greg St.Onge
fuente
3

Extendiéndose a partir de la respuesta de Rapti , esto debería funcionar igual de bien, pero agrega más margen al lado derecho del bodyy lo oculta con htmlmargen negativo , en lugar de agregar relleno adicional que podría afectar el diseño de la página. De esta manera, no se cambia nada en la página real (en la mayoría de los casos) y el código sigue siendo funcional.

html {
    margin-right: calc(100% - 100vw);
}
body {
    margin-right: calc(100vw - 100%);
}
Grant Gryczan
fuente
Descubrí que en Chrome esto agrega un desplazamiento horizontal en las páginas que tienen una barra de desplazamiento vertical en mi sitio de arranque.
Ginger Squirrel
¿Has intentado investigar por qué? Verifique el inspector de elementos y vea si Bootstrap se mete con márgenes, barras de desplazamiento o algo así.
Grant Gryczan
1
Probablemente tuvo algo que ver con los márgenes de 15px que bootstrap pone en todo, al inspeccionar la página, el margen del contenedor cae debajo de la barra de desplazamiento. Lo apliqué overflow-x: hiddeny eso lo arregló.
Ginger Squirrel
3

La solución de @ kashesandr funcionó para mí, pero para ocultar la barra de desplazamiento horizontal agregué un estilo más para el cuerpo. Aquí está la solución completa:

CSS

<style>
/* prevent layout shifting and hide horizontal scroll */
html {
  width: 100vw;
}
body {
  overflow-x: hidden;
}
</style>

JS

$(function(){
    /**
     * For multiple modals.
     * Enables scrolling of 1st modal when 2nd modal is closed.
     */
    $('.modal').on('hidden.bs.modal', function (event) {
      if ($('.modal:visible').length) {
        $('body').addClass('modal-open');
      }
    });
});

Solución JS Only (cuando el segundo modal se abrió desde el primer modal):

/**
 * For multiple modals.
 * Enables scrolling of 1st modal when 2nd modal is closed.
 */
$('.modal').on('hidden.bs.modal', function (event) {
  if ($('.modal:visible').length) {
    $('body').addClass('modal-open');
    $('body').css('padding-right', 17);
  }
});
Hassan Tareq
fuente
2

Traté de solucionar el probable problema al que se .modal-openaplicaba la clase bootstrap de Twitter body. La solución html {overflow-y: scroll}no ayuda. Una posible solución que encontré es agregar {width: 100%; width: 100vw}al htmlelemento.

kashesandr
fuente
1
o cámbielo a cuerpo {overflow-y: scroll}
Ruben
1
Pero eso siempre mostraría una barra de desplazamiento, incluso si no es necesario.
Rapti
Debería explicar por qué está configurando el ancho dos veces? html { width: 100vw; }trabajado para mí
Hassan Tareq
Para mí, en realidad crea dos barras de desplazamiento
rbansal
2

Solía ​​tener ese problema, pero la forma más simple de solucionarlo es esto (esto funciona para mí):

en el tipo de archivo CSS:

body{overflow-y:scroll;}

así de simple! :)

Melvin Guerrero
fuente
2

Las soluciones publicadas usando calc (100vw - 100%) están en el camino correcto, pero hay un problema con esto: siempre tendrá un margen a la izquierda del tamaño de la barra de desplazamiento, incluso si cambia el tamaño de la ventana para que el el contenido llena toda la ventana gráfica.

Si intenta evitar esto con una consulta de medios, tendrá un momento de ajuste incómodo porque el margen no se reducirá progresivamente a medida que cambie el tamaño de la ventana.

Aquí hay una solución que evita eso y AFAIK no tiene inconvenientes:

En lugar de usar margin: auto para centrar su contenido, use esto:

body {
margin-left: calc(50vw - 500px);
}

Reemplace 500 px con la mitad del ancho máximo de su contenido (en este ejemplo, el ancho máximo del contenido es 1000 px). El contenido ahora permanecerá centrado y el margen disminuirá progresivamente hasta que el contenido llene la ventana gráfica.

Para evitar que el margen se vuelva negativo cuando la ventana gráfica es más pequeña que el ancho máximo, simplemente agregue una consulta de medios como esta:

@media screen and (max-width:1000px) {
    body {
        margin-left: 0;
    }
}

Et voilà!

Jonathan SI
fuente
2

Si el ancho de la tabla no cambia, puede establecer el ancho del elemento (como tbody) que contiene la barra de desplazamiento> 100% (permitiendo espacio adicional para la barra de desplazamiento) y establecer overflow-y en "overlay" (por lo tanto que la barra de desplazamiento permanece fija y no desplazará la tabla hacia la izquierda cuando aparezca). Establezca también una altura fija para el elemento con la barra de desplazamiento, de modo que la barra de desplazamiento aparecerá una vez que se exceda la altura. Al igual que:

tbody {
  height: 100px;
  overflow-y: overlay;
  width: 105%
}

Nota: tendrá que ajustar manualmente el% de ancho ya que el% de espacio que ocupa la barra de desplazamiento será relativo al ancho de su tabla (es decir: ancho de tabla más pequeño, se requiere más% para ajustarse a la barra de desplazamiento, ya que su tamaño en píxeles es constante )

Un ejemplo de tabla dinámica:

function addRow(tableID)
{
    var table = document.getElementById(tableID);
    var rowCount = table.rows.length;
    var row = table.insertRow(rowCount);
    var colCount = table.rows[0].cells.length;
  
    for(var i=0; i<colCount; i++)
    {
        var newRow = row.insertCell(i);

        newRow.innerHTML = table.rows[0].cells[i].innerHTML;
        newRow.childNodes[0].value = "";
    }
}
 
function deleteRow(row)
{
    var table = document.getElementById("data");
    var rowCount = table.rows.length;
    var rowIndex = row.parentNode.parentNode.rowIndex;

    document.getElementById("data").deleteRow(rowIndex);
}
.scroll-table {
  border-collapse: collapse;
}

.scroll-table tbody {
  display:block;
  overflow-y:overlay;
  height:60px;
  width: 105%
}

.scroll-table tbody td {
  color: #333;
  padding: 10px;
  text-shadow: 1px 1px 1px #fff;
}

.scroll-table thead tr {
  display:block;
}

.scroll-table td {
    border-top: thin solid; 
    border-bottom: thin solid;
}

.scroll-table td:first-child {
    border-left: thin solid;
}

.scroll-table td:last-child {
    border-right: thin solid;
}

.scroll-table tr:first-child {
    display: none;
}

.delete_button {
    background-color: red;
    color: white;
}

.container {
  display: inline-block;
}

body {
  text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="test_table.css">
</head>

<body>
<h1>Dynamic Table</h1>
<div class="container">

  <table id="data" class="scroll-table">
    <tbody>
      <tr>
        <td><input type="text" /></td>
        <td><input type="text" /></td>
        <td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
      </tr>
    </tbody>
  </table>

  <input type="button" value="Add" onclick="addRow('data')" />

</div>

<script src="test_table.js"></script>
</body>
</html>

Robert James Mieta
fuente
1

Simplemente establecer el ancho de su elemento contenedor de esta manera hará el truco

width: 100vw;

Esto hará que ese elemento ignore la barra de desplazamiento y funcione con imágenes o color de fondo.

Barsonax
fuente
-3

Utilicé un poco de jquery para resolver esto

$('html').css({
    'overflow-y': 'hidden'
});

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});
Will McMillian
fuente
3
Es probable que obtenga una mala recepción de su respuesta porque esta solución requiere un marco JavaScript completo. "jQuery todas las cosas!"
Paul Lammertsma
3
sí, jQuery es definitivamente el camino a seguir - doxdesk.com/img/updates/20091116-so-large.gif
Anónimo
-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}
Vicky
fuente
¡Bienvenido a Stack Overflow! Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código. Por favor, también trate de no saturar su código con comentarios explicativos, ¡esto reduce la legibilidad tanto del código como de las explicaciones!
Andrew Myers
-5

Contrariamente a la respuesta aceptada que sugiere una barra de desplazamiento permanente en la ventana del navegador, incluso si el contenido no desborda la pantalla , preferiría usar:

html{
  height:101%;
}

Esto se debe a que la apariencia de la barra de desplazamiento tiene más sentido si el contenido se desborda .

Esto tiene más sentido que esto .

Nikunj Madhogaria
fuente
1
Al menos la última oración es incorrecta en tu respuesta. Tiene sentido similar con el exceso de página vacía impresa por la impresora.
vp_arth