Como impedir que a barra de rolagem reposicione a página da web?

218

Eu tenho um site com DIV alinhado ao centro. Agora, algumas páginas precisam ser roladas, outras não. Quando passo de um tipo para outro, a aparência de uma barra de rolagem move a página alguns pixels para o lado. Existe alguma maneira de evitar isso sem mostrar explicitamente as barras de rolagem em cada página?

Dmitri Nesteruk
fonte
6
Por que ninguém menciona overflow-y: overlayneste tópico?
milkersarac
3
De acordo com os documentos do mozilla, overflow-y: overlayé depreciado: developer.mozilla.org/pt-BR/docs/Web/CSS/overflow
drojf 16/04/19

Respostas:

266

overflow-y: scroll está correto, mas você deve usá-lo com a tag html, não body, ou então obterá uma barra de rolagem dupla no IE 7.
Portanto, o css correto seria:

html {
  overflow-y: scroll;
}
Ruben
fonte
1
IE 10+ tem uma barra de rolagem flutuante para que você deve desativar esta para estes navegadores
Ruben
1
isso pode causar problemas, como barras de posicionamento quando se utiliza duplas em combinação com fancybox ou twitter de bootstrap modal
Ruben
Informação extra: inicialização do twitter agora adiciona .modal-aberto para você corpo quando um modal está aberta
Ruben
55
Vale ressaltar que isso mostra permanentemente uma barra de rolagem vertical. Nem sempre pode ser aceitável.
Rustyx
Recebo uma barra de rolagem dupla no Chromium e no Firefox. Estou usando caixa flexível; talvez que está causando isso ...
Garrett
72

Coloque o conteúdo do seu elemento rolável em uma div e 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>

O truque é que 100vwrepresenta 100% da janela de visualização, incluindo a barra de rolagem. Se você subtrair 100%, que é o espaço disponível sem a barra de rolagem, você terá a largura da barra de rolagem ou 0se ela não estiver presente. Criar um preenchimento dessa largura à esquerda simulará uma segunda barra de rolagem, deslocando o conteúdo centralizado de volta para a direita.

Observe que isso só funcionará se o elemento rolável usar toda a largura da página, mas isso não deve ser um problema na maioria das vezes, porque existem apenas alguns outros casos em que você centralizou o conteúdo rolável.

Rapti
fonte
1
Seria melhor aplicado através de uma classe do que um estilo embutido, e só funcionará nesses navegadores , mas é uma técnica inteligente - eu não tinha percebido isso 100vwe 100%medido coisas diferentes, então aprendi algo útil com isso!
Nick F
21
Isso é absolutamente genial e é realmente a melhor resposta, considerando que o suporte ao navegador para o calc é muito bom.
23616 Michael
1
Você pode fazer o mesmo, exceto que, em vez de adicionar uma margem à esquerda, adicione uma margem negativa à direita (consulte stackoverflow.com/a/39289453/6015444 ).
Touniouk
2
Esta solução causará problemas semelhantes à cor do plano de fundo, como a resposta "width: calc (100vw - 34px);" mas no lado esquerdo.
Maciej Lew
1
Eu recomendaria adicionar algumas consultas de mídia a este estilo @media screen and (min-width: 800px) {...} . Nos casos em que o conteúdo caberá na largura da página. Por exemplo, em pequenas resoluções haverá lacuna desnecessários, mudando o conteúdo para a direita
MarkosyanArtur
44

Eu acho que não. Mas estilizar bodycom overflow: scrolldeve servir. Você parece saber disso, no entanto.

Michael Krelin - hacker
fonte
3
Parece bom ... force a página a sempre mostrar a barra de rolagem, seja ou não necessária, ... então não haverá alteração visual entre os tipos de página.
eidylon
1
Sim, mas IIRC, isso mostra as duas barras de rolagem. Eu realmente não preciso da horizontal.
Dmitri Nesteruk
Isso é verdade. Mas não há muito que eu possa fazer para ajudá-lo :( Na verdade, eu só consideram a primeira frase da minha resposta para ser a verdadeira resposta que lida com a questão.
Michael Krelin - hacker de
49
overflow-y: scroll:)
Svish
2
A seguir é a melhor resposta
Sami
36

Com a rolagem sempre sendo exibida, talvez não seja bom para o layout.

Tente limitar a largura do corpo com css3

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

vwé a largura da janela de exibição (veja este link para obter algumas explicações)
calccalcular em css3
34pxsignifica largura da barra de rolagem dupla (veja isso para fixo ou para calcular se você não confia em tamanhos fixos)

Moesio
fonte
4
Tudo é futilidade até que alguém precise.
Moesio
3
Visualmente, isso é muito menos invasivo do que apenas forçar barras de carregamento, como a resposta aceita descreve.
Silas Hansen
4
Até agora, isso funcionou melhor para minhas necessidades, também adicionei padding-left: 34px;para centralizar uniformemente minha página.
Pat Migliaccio 10/10
3
Essa deve ser a resposta aceita, ao contrário da atualmente aceita, ela está respondendo à pergunta!
Coz
2
Isto irá causar problemas se você tem navbar / cabeçalho com cor diferente do corpo fundo ou borda inferior etc.
Zia Ul Rehman Mughal
28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

Exemplo . Clique no botão "alterar altura mínima".

Com calc(100vw - 100%)podemos calcular a largura da barra de rolagem (e, se não for exibida, será 0). Idéia: usando margem negativa direita, podemos aumentar a largura <html>para essa largura. Você verá uma barra de rolagem horizontal - ela deve estar oculta usando overflow-x: hidden.

pongo
fonte
Eu tive que colocar o corpo em uma div e aplicar a margem à div para que funcionasse (semelhante à resposta de Rapti .) Mas isso parece muito mais limpo.
Touniouk
1
Isso funciona muito bem e não parece resultar em barras de rolagem horizontais indesejadas no Chrome ou Firefox. Por que não usar apenas ao calc(100% - 100vw)invés de multiplicar -1?
SystemParadox
13

Não sei se este é um post antigo, mas tive o mesmo problema e se você quiser rolar verticalmente, tente overflow-y:scroll


fonte
13

Se alterar o tamanho ou depois de carregar alguns dados, estiver adicionando a barra de rolagem, você pode tentar seguir, criar classe e aplicar essa classe.

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

Resolvi o problema em um dos meus sites, definindo explicitamente a largura do corpo em javascript pelo tamanho da janela de exibição menos a largura da barra de rolagem. Eu uso uma função baseada em jQuery documentada aqui para determinar a largura da barra de rolagem.

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Frank L
fonte
10
Não posso nem começar a explicar por que essa é uma prática tão ruim.
Mythofechelon
20
@ BenHooper: Eu gostaria de saber por que isso é uma prática ruim.
Saad
1
O que acontece se você redimensionar a janela?
Braden Steffaniak
3

Expandindo a resposta usando isso:

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

Um comentarista sugeriu a adição de preenchimento à esquerda também para manter a centralização:

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

Mas as coisas não parecerão corretas se o seu conteúdo for maior que a janela de visualização. Para corrigir isso, você pode usar consultas de mídia, assim:

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

Onde 1058 px = largura do conteúdo + 17 * 2

Isso permite que uma barra de rolagem horizontal lide com o excesso de x e mantém o conteúdo centralizado quando a janela de exibição é ampla o suficiente para conter seu conteúdo de largura fixa

Greg St.Onge
fonte
3

Estendendo-se de a resposta do Rapti , isso também deve funcionar, mas adiciona mais margem ao lado direito bodye oculta com htmlmargem negativa , em vez de adicionar preenchimento extra que pode afetar o layout da página. Dessa forma, nada é alterado na página real (na maioria dos casos) e o código ainda está funcional.

html {
    margin-right: calc(100% - 100vw);
}
body {
    margin-right: calc(100vw - 100%);
}
Grant Gryczan
fonte
Descobri que no chrome isso adiciona uma rolagem horizontal nas páginas que possuem uma barra de rolagem vertical no meu site de inicialização.
Ginger Squirrel
Você já tentou descobrir por quê? Verifique o inspetor de elementos e veja se o Bootstrap mexe com margens, barras de rolagem ou algo assim.
Grant Gryczan
1
Provavelmente, tinha algo a ver com as margens de 15px que o bootstrap coloca em tudo, ao inspecionar a página, a margem do contêiner fica abaixo da barra de rolagem. Eu apliquei overflow-x: hiddene isso foi corrigido.
Ginger Squirrel
3

A solução do @ kashesandr funcionou para mim, mas para ocultar a barra de rolagem horizontal, adicionei mais um estilo ao corpo. aqui está a solução 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');
      }
    });
});

Solução JS Only (quando o 2º modal foi aberto a partir do 1º 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
fonte
2

Tentei corrigir provavelmente o mesmo problema causado pela .modal-openclasse de inicialização do twitter aplicada body. A solução html {overflow-y: scroll}não ajuda. Uma solução possível que encontrei é adicionar {width: 100%; width: 100vw}ao htmlelemento.

kashesandr
fonte
1
ou altere-o para body {overflow-y: scroll}
Ruben
1
Mas isso sempre exibirá uma barra de rolagem, mesmo que não seja necessária.
Rapti
Você deve explicar por que está definindo a largura duas vezes? html { width: 100vw; }funcionou para mim #
2139 Hassan Tareq
Para mim, ele realmente cria duas barras de rolagem
rbansal 16/02
2

Eu costumava ter esse problema, mas a maneira simples de corrigi-lo é esta (isso funciona para mim):

no tipo de arquivo CSS:

body{overflow-y:scroll;}

tão simples assim! :)

Melvin Guerrero
fonte
2

As soluções postadas usando calc (100vw - 100%) estão no caminho certo, mas há um problema com isso: você sempre terá uma margem à esquerda do tamanho da barra de rolagem, mesmo se redimensionar a janela para que o o conteúdo preenche toda a janela de exibição.

Se você tentar contornar isso com uma consulta de mídia, terá um momento de embaraço estranho, porque a margem não ficará progressivamente menor à medida que você redimensionar a janela.

Aqui está uma solução que contorna isso e o AFAIK não tem desvantagens:

Em vez de usar margin: auto para centralizar seu conteúdo, use o seguinte:

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

Substitua 500 px pela metade da largura máxima do seu conteúdo (portanto, neste exemplo, a largura máxima do conteúdo é 1000 px). O conteúdo agora permanecerá centralizado e a margem diminuirá progressivamente até o conteúdo preencher a janela de exibição.

Para impedir que a margem fique negativa quando a viewport for menor que a largura máxima, adicione uma consulta de mídia da seguinte forma:

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

Et voilà!

Jonathan SI
fonte
2

Se a largura da tabela não for alterada, você poderá definir a largura do elemento (como tbody) que contém a barra de rolagem> 100% (permitindo espaço extra para a barra de rolagem) e definir overflow-y como "overlay" (assim que a barra de rolagem permanece fixa e não muda a tabela para a esquerda quando aparece). Defina também uma altura fixa para o elemento com a barra de rolagem, para que a barra de rolagem apareça quando a altura for excedida. Igual a:

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

Nota: você terá que ajustar manualmente a largura%, pois o% de espaço ocupado pela barra de rolagem será relativo à largura da sua tabela (ou seja: largura menor da tabela, mais% necessário para ajustar a barra de rolagem, pois o tamanho em pixels é constante )

Um exemplo de tabela 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
fonte
1

Basta definir a largura do seu elemento de contêiner dessa maneira.

width: 100vw;

Isso fará com que esse elemento ignore a barra de rolagem e funcione com cores ou imagens de plano de fundo.

Barsonax
fonte
-3

Eu usei algum jquery para resolver isso

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

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});
Will McMillian
fonte
3
É provável que você receba uma resposta ruim porque sua solução requer uma estrutura JavaScript inteira. "jQuery todas as coisas!"
Paul Lammertsma
3
Sim, o jQuery é definitivamente o caminho a seguir - doxdesk.com/img/updates/20091116-so-large.gif
Anônimo
-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}
Vicky
fonte
Bem-vindo ao Stack Overflow! Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Por favor, tente também não sobrecarregar seu código com comentários explicativos, isso reduz a legibilidade do código e das explicações!
Andrew Myers
-5

Ao contrário da resposta aceita, que sugere uma barra de rolagem permanente na janela do navegador, mesmo que o conteúdo não ultrapasse a tela , eu prefiro usar:

html{
  height:101%;
}

Isso ocorre porque a aparência da barra de rolagem faz mais sentido se o conteúdo realmente exceder o limite .

Isso faz mais sentido do que isso .

Nikunj Madhogaria
fonte
1
Pelo menos a última frase está errada em sua resposta. Faz sentido semelhante ao excesso de página vazia impressa pela impressora.
vp_arth