javascript - traversing - Como faço para impedir que meu conteúdo da Web seja deslocado para a esquerda quando a barra de rolagem vertical aparecer? Roll-Up of Advice 2017



scroll suave bootstrap 4 (1)

Muitos programadores perguntaram como parar o conteúdo de sua página da Web - especialmente o conteúdo de sua página centralizada ( margin: 0 auto; ) - da movimentação horizontal (horizontal) quando a barra de rolagem vertical aparece. Esse tem sido um problema contínuo para usuários do Ajax e pessoas como eu que usam divs e guias ocultas para organizar dados.

O problema ocorre quando a página exibida no momento muda de forma que a altura do material exibido (a altura da janela interna) é subitamente maior que a altura da janela física.

O problema é exacerbado pela realidade de que todas as barras de rolagem não são criadas iguais. Navegadores diferentes dão a suas barras de rolagem larguras diferentes, e essa diferença não pode (ou, pelo menos, não deve) ser prevista. Em suma, a solução ideal é a largura da barra de rolagem independente.

Essa é, portanto, uma pergunta auto-respondida que rola todas as respostas com comentários sobre sua utilidade (quando possível) junto com minha própria solução em uma única resposta a partir de 5 de agosto de 2017. Marquei como duplicatas muitas das respostas. perguntas anteriores, como posso encontrar, para que as pessoas possam encontrar uma discussão abrangente sobre o assunto.

Por favor, note que esta resposta aborda problemas com mudança de conteúdo BODY. Se você tiver um DIV com uma altura fixa que tenha problemas de deslocamento, defina a largura DIV para uma largura fixa ( px ) para que sua barra de rolagem flutue acima do texto e adicione um preenchimento à direita para evitar que o texto caia abaixo dele. Colaboradores: Hashbrown , Avrahamcool , Edward Newsome


Antes de entrar em soluções individuais, deve-se mencionar que elas se dividem em três categorias: CSS, CSS3 e soluções baseadas em Javascript.

As soluções CSS tendem a ser sulcadas, mas muito previsíveis e muito bem suportadas.

As soluções CSS3 têm um custo de cálculo da CPU como o Javascript, mas são fáceis de implementar. Nos anos anteriores a 2017, no entanto, eles tinham suporte esporádico em navegadores. Isso está melhorando ao longo do tempo. Em última análise, eles provavelmente serão a melhor solução, mas minhas próprias investigações hoje demonstraram que o suporte simplesmente ainda não é consistente o suficiente e, além disso, o suporte ao navegador legado é inexistente.

As soluções de Javascript (seja em Javascript direto ou em jQuery) precisam de codificação extra para torná-las robustas, pois não possuem suporte intrínseco para (por exemplo) redimensionamento de janelas. No entanto, eles são os mais previsíveis e os mais retrocompatíveis, preservando a estética da página. Eu considero a linha para navegadores herdados entre o IE6 e o ​​IE7. Francamente, minhas condolências a quem ainda usa um navegador tão antigo.

Por favor, note que eu não incluí todas as soluções CSS3 e Javascript postadas anteriormente no Stack Exchange. Alguns, embora novos, tinham fraquezas substanciais e, portanto, não foram incluídos aqui.

Solução # 1: A Solução CSS

Colaboradores: Hive7 , koningdavid , Christofer Eliasson , Alec Gorge , Bartell Scott , Shawn Taylor , mVChr , fsn , Damb , Sparky , Ruben , Michael Krelin - hacker , Melvin Guerreiro

Force a barra de rolagem a estar sempre ligada.

<style>
html {
    overflow-y: scroll;
}
</style>

Esta solução é basicamente garantida para sempre funcionar (existem algumas exceções, mas elas são muito raras), mas é esteticamente desagradável. A barra de rolagem sempre será vista, seja ela necessária ou não. Embora o consenso seja usar essa solução na tag html , algumas pessoas sugerem usá-la na tag body .

Consequências

A Microsoft (IE10 +) implentou barras de rolagem flutuantes, o que significa que sua página pode não estar centralizada como em outros navegadores. No entanto, esta parece ser uma questão muito menor.

Ao usar interfaces estruturadas como FancyBox, Flex-Box ou Twitter Bootstrap Modal, isso pode fazer com que uma barra de rolagem dupla apareça, já que essas interfaces criam suas próprias barras de rolagem.

Os programadores devem evitar o uso de overflow: scroll conforme isso fará com que as barras de rolagem vertical e horizontal apareçam.

Solução # 1a: uma alternativa

Colaboradores: koningdavid , Nikunj Madhogaria

Uma alternativa inteligente, mas com apenas uma pequena diferença estética, é fazer isso:

<style>
html {
    height: 101%;
}
</style>

Isso ativa o plano de fundo da barra de rolagem, mas não ativa a guia da barra de rolagem, a menos que seu conteúdo vertical realmente ultrapasse a borda inferior da janela. No entanto, tem a mesma fraqueza em que o espaço da barra de rolagem é permanentemente consumido, seja necessário ou não.

Solução # 1b: uma solução mais moderna

Colaboradores: Kyle Dumovic , SimonDos

Os navegadores estão começando a pegar o uso do valor de overlay para barras de rolagem, imitando a barra de rolagem flutuante do IE10 +.

<style>
html {
    overflow-y: overlay;
}
</style>

Esta solução imita a barra de rolagem flutuante no IE10 +, mas ainda não está disponível em todos os navegadores e ainda tem algumas peculiaridades de implementação. Esta solução é conhecida por não funcionar em ambientes de infraestrutura como o Bootstrap Modal.

Solução 2: A Solução CSS3

Use CSS3 para calcular larguras. Há muitas maneiras de fazer isso com vantagens e desvantagens para cada um. A maioria das desvantagens se deve a (a) não saber a largura real da barra de rolagem, (b) lidar com o redimensionamento da tela e (c) o fato de que o CSS está lentamente se tornando linguagem de programação em funcionamento - como Javascript - mas ainda não completamente evoluiu para tal. Se faz ou não sentido fazer isso, é um debate para outra questão.

O argumento de que os usuários podem desativar o Javascript e, portanto, uma solução somente de CSS é preferível, está se tornando irrelevante. A programação do lado do cliente tornou-se tão onipresente que apenas as pessoas mais paranoicas ainda estão desabilitando o Javascript. Pessoalmente, não considero mais esse argumento sustentável.

Deve-se notar que algumas soluções modificam a margin e outras modificam o padding . Aqueles que modificam a margin têm um problema comum: se você tem barras de navegação, cabeçalhos, bordas, etc., que usam uma cor diferente do fundo da página, esta solução irá expor bordas indesejáveis. É provável que qualquer solução usando margin possa ser reprojetada para usar o padding e vice-versa.

Solução # 2a: A solução baseada em HTML

Colaboradores: TranslucentCloud , Mihail Malostanidis

<style>
html {
    margin-left: calc(100vw - 100%);
    margin-right: 0;
}
</script>

Solução # 2b: A solução baseada no corpo

Colaboradores: Greg St.Onge , Moesio , Jonathan SI

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

100vw é 100% da largura da janela de visualização.

Consequências

Alguns usuários sugeriram que essa solução cria um ruído indesejado na tela quando a janela é redimensionada (talvez o processo de cálculo esteja ocorrendo várias vezes durante o processo de redimensionamento). Uma possível solução alternativa é evitar o uso de margin: 0 auto; para centralizar o seu conteúdo e, em vez disso, use o seguinte (os 1000px e 500px mostrados no exemplo representam a largura máxima do seu conteúdo e a metade desse valor, respectivamente):

<style>
body {
    margin-left: calc(50vw - 500px);
}
@media screen and (max-width: 1000px) {
    body {
        margin-left: 0;
    }
}
</style>

Essa é uma solução de largura de barra de rolagem fixa, que não é independente do navegador. Para torná-lo independente do navegador, você deve incluir o Javascript para determinar a largura das barras de rolagem. Um exemplo que calcula a largura mas não reincorpora o valor é:

Observe que o snippet de código abaixo foi publicado várias vezes no Stack Exchange e em outros locais na Internet na íntegra, sem atribuição firme.

function scrollbarWidth() {
    var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
    // Append our div, do our calculation and then remove it
    $('body').append(div);
    var w1 = $('div', div).innerWidth();
    div.css('overflow-y', 'scroll');
    var w2 = $('div', div).innerWidth();
    $(div).remove();
    return (w1 - w2);
}

Solução # 2c: A solução baseada em DIV

Contribuintes: Rapti

Use os cálculos CSS3 aplicados diretamente a um elemento DIV do contêiner.

<body>
    <div style="padding-left: calc(100vw - 100%);">
    My Content
    </div>
</body>

Consequências

Como todas as soluções CSS3, isso não é suportado por todos os navegadores. Mesmo aqueles navegadores que suportam cálculos de viewport não suportam o seu uso arbitrariamente (a partir da data deste artigo).

Solução # 2d: Bootstrap Modal

Contribuintes: Mihail Malostanidis , kashesandr

Os usuários do Twitter Bootstrap Modal acharam útil aplicar o seguinte CSS3 ao seu elemento HTML.

<style>
html {
    width: 100%;
    width: 100vw;
}
</style>

Outra sugestão é criar um wrapper em torno do wrapper de conteúdo usado para detectar alterações automaticamente na largura da viewport.

<style>
body {
    overflow-x: hidden;
}
#wrap-wrap {
    width: 100vw;
}
#content-wrap {
    margin: 0 auto;
    width: 800px;
}
</style>

Eu não tentei nenhum desses como eu não uso Bootstrap.

Solução # 3: A Solução Javascript

Colaboradores: Sam ,

Esta é a minha solução favorita, pois lida com todos os problemas e é relativamente compatível com os navegadores legados. O melhor de tudo, é independente da largura da barra de rolagem.

<script>
function updateWindow(){
    document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
    document.body.onclick=function(){
            document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
    }
}
window.onload=updateWindow();
window.addEventListener("resize", updateWindow());
updateWindow();
</script>

Consequências

O comando final para updateWindow(); deve ocorrer antes da tag </body> para evitar problemas com conteúdo carregado dinamicamente, como o Facebook Like-Boxes. Parece que ele é redundante para o evento window.onload , mas nem todo navegador trata onload da mesma maneira. Alguns esperam por eventos assíncronos. Outros não.

A função é executada sempre que um usuário clica na página da web. Felizmente, os computadores modernos são rápidos o suficiente para que isso não seja um problema. Ainda….

Finalmente, a função deve ser executada após qualquer div ser atualizado de forma assíncrona (AJAX). Isso não é mostrado neste exemplo, mas seria parte da condição de estado pronto. Por exemplo:

xmlhttp.onreadystatechange=function(){
    if(xmlhttp.readyState==4 && xmlhttp.status==200){
        if(xmlhttp.responseText == 'false'){
            //Error processing here
        } else {
            //Success processing here
            updateWindow();
        }
    }
}

Solução 3a: Medindo larguras da barra de rolagem

Contribuintes: Lwyrn

Essa é uma solução menos valiosa que leva tempo para medir as larguras da barra de rolagem.

<script>
var checkScrollBars = function(){
    var b = $('body');
    var normalw = 0;
    var scrollw = 0;
    if(b.prop('scrollHeight')>b.height()){
        normalw = window.innerWidth;
        scrollw = normalw - b.width();
        $('#container').css({marginRight:'-'+scrollw+'px'});
    }
}
</script>
<style>
body {
    overflow-x: hidden;
}
</style>

Consequências

Como outras soluções, esta desativará permanentemente a barra de rolagem horizontal.





css3