Detectar se uma página tem uma barra de rolagem vertical?

121

Eu só quero que um JQ / JS simples verifique se a página / janela atual (não um elemento específico) tem uma barra de rolagem vertical.

O Google me fornece coisas que parecem excessivamente complexas apenas para esse recurso básico.

Como isso pode ser feito?

Woody
fonte

Respostas:

97
$(document).ready(function() {
    // Check if body height is higher than window height :)
    if ($("body").height() > $(window).height()) {
        alert("Vertical Scrollbar! D:");
    }

    // Check if body width is higher than window width :)
    if ($("body").width() > $(window).width()) {
        alert("Horizontal Scrollbar! D:<");
    }
});
Thiago Belem
fonte
14
+1, mas por uma questão de exatidão, isso verifica apenas se o conteúdo se expande além da janela de visualização. Se a overflowpropriedade do bodyestiver definida em hiddenalgum lugar ao longo da linha, não funcionará. Colocar o corpo escondido é extremamente raro, no entanto.
Pekka
4
Isso não funcionará se a altura do corpo corresponder à altura da janela, que é o caso se a altura do documento corresponder exatamente à janela de visualização e, em seguida, uma barra de rolagem horizontal será adicionada . Isso forçará vert. barra de rolagem, mas a altura de doc / body / window é a mesma; NÃO alertará a "barra de rolagem vertical" mesmo que exista uma.
Pare de caluniar Monica Cellio
2
Apenas pensei em mencionar que eu tinha que usar $(document)em vez de $("body"), isso funcionou para mim quando o corpo não (eu tenho um recipiente positoned absoluta com uma relação de aspecto de largura / altura)
AM_
1
Tenho uma página de relatório no navegador Chrome, onde ele exibe inicialmente uma barra de rolagem e desaparece em questão de milissegundos, que se parece com o comportamento de um navegador, pois eu não a programei. Então esta função return true sempre no meu caso ..
Dush
O @TiuTalk para mim $ ("body"). Height () e $ (window) .height () fornece o mesmo valor; em vez disso, uso $ (document) .height ()> $ (window) .height () para mim.
SarangK
77

tente isto:

var hasVScroll = document.body.scrollHeight > document.body.clientHeight;

No entanto, isso informa apenas se o scrollHeight vertical é maior que a altura do conteúdo visível. A hasVScrollvariável conterá verdadeiro ou falso.

Se você precisar fazer uma verificação mais completa, adicione o seguinte ao código acima:

// Get the computed style of the body element
var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");

// Check the overflow and overflowY properties for "auto" and "visible" values
hasVScroll = cStyle.overflow == "visible" 
             || cStyle.overflowY == "visible"
             || (hasVScroll && cStyle.overflow == "auto")
             || (hasVScroll && cStyle.overflowY == "auto");
Andy E
fonte
1
+1 Bom! E com o estilo computadorizada necessária (que era o ponto em que eu decidi não se envolver com esta questão;)
Pekka
lol sim, eu estava pensando se deveria ou não fazer um esforço extra para escrevê-lo, porque em muitos casos isso não é necessário.
Andy E
1
Isso resulta em hasVScroll sendo verdadeiro sempre que overflowY for 'visível', independentemente de o scrollHeight ser maior que o clientHeight. Talvez você quis dizer cStyle.overflow === 'scroll'?
BT
5
O código acima não funciona. Navegador: Chrome 56. Url: news.greylock.com/…
Sebastien Lorber
1
O @BT cStyle.overflow == "visible" pode mostrar barras de rolagem quando o elemento é o document.body. Mas deve ser (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY"). Além disso, ele precisa verificar cStyle.overflow === 'scroll'como você aponta.
Mseifert #
44

Eu tentei a resposta anterior e não parece estar trabalhando com o $ ("body"). Height () não representa necessariamente toda a altura do html.

Corrigi a solução da seguinte maneira:

// Check if body height is higher than window height :) 
if ($(document).height() > $(window).height()) { 
    alert("Vertical Scrollbar! D:"); 
} 

// Check if body width is higher than window width :) 
if ($(document).width() > $(window).width()) { 
    alert("Horizontal Scrollbar! D:<"); 
} 
Bharat
fonte
18

Vamos trazer essa pergunta de volta dos mortos;) Há uma razão pela qual o Google não fornece uma solução simples. Casos especiais e peculiaridades do navegador afetam o cálculo, e não é tão trivial quanto parece.

Infelizmente, existem problemas com as soluções descritas aqui até agora. Não pretendo menosprezá-los - eles são ótimos pontos de partida e abordam todas as principais propriedades necessárias para uma abordagem mais robusta. Mas eu não recomendaria copiar e colar o código de nenhuma das outras respostas, porque

  • eles não capturam o efeito do conteúdo posicionado de maneira confiável em vários navegadores. As respostas que se baseiam no tamanho do corpo perdem completamente isso (o corpo não é o pai deslocado de tal conteúdo, a menos que esteja em si). E essas respostas checam $( document ).width()e .height()caem na detecção de bugs do tamanho do documento pelo jQuery .
  • Confiar window.innerWidth, se o navegador suportar, faz com que seu código falhe na detecção de barras de rolagem em navegadores móveis, onde a largura da barra de rolagem é geralmente igual a 0. Elas são mostradas temporariamente como uma sobreposição e não ocupam espaço no documento . O zoom no celular também se torna um problema dessa maneira (longa história).
  • A detecção pode ser iniciada quando as pessoas definem explicitamente o estouro de ambos os elementos htmle bodypara valores não padrão (o que acontece, então, é um pouco envolvido - veja esta descrição ).
  • Na maioria das respostas, o preenchimento do corpo, bordas ou margens não são detectados e distorcem os resultados.

Passei mais tempo do que eu imaginava em encontrar uma solução que "simplesmente funcionasse" (tosse). O algoritmo que criei agora faz parte de um plugin, jQuery.isInView , que expõe um .hasScrollbarmétodo . Dê uma olhada na fonte, se desejar.

Em um cenário em que você tem controle total da página e não precisa lidar com CSS desconhecido, o uso de um plug-in pode ser um exagero - afinal, você sabe quais casos extremos se aplicam e quais não. No entanto, se você precisar de resultados confiáveis ​​em um ambiente desconhecido, não acho que as soluções descritas aqui sejam suficientes. É melhor usar um plug-in bem testado - o meu ou qualquer outro.

hashchange
fonte
Obrigado. Um pouco complicado! Se você não deseja / precisa ser compatível com versões anteriores, talvez haja uma solução mais fácil para os navegadores html5? Quero dizer, talvez os codificadores do navegador / w3c tenham sido bons o suficiente para nos dizer se há barras de rolagem ou não em um elemento? ;-)
Leo
1
@ Leo Não que eu esteja ciente. Bem, há um window.scrollbarsobjeto que possui uma única propriedade visible,. Parece promissor, mas não é. Não é suportado no IE, incluindo o IE11. E apenas informa que existe uma barra de rolagem - mas não qual. Veja a página de teste aqui .
hashchange
Obrigado @hashchange. Parece incrivelmente estúpido dizer apenas se existe alguma barra de rolagem, então acho que ainda é algum tipo de teste. Um pouco promissor. ;-) #
1764
1
@ BT Ok, ótimo. Agora, deixe-me levá-lo à entrada da toca do coelho;) Aqui está uma demonstração em que o conteúdo não é suficiente para preencher a janela. Sua detecção funciona no FF, mas falha no Chrome. E aqui está outra demonstração em que um elemento posicionado é colocado na parte inferior da página. Sua detecção funciona no Chrome, mas falha no FF.
Hashchange
1
@BT E acho que podemos entrar em vários modos de falha estranhos quando começamos a jogar com configurações de estouro porque o comportamento delas é um pouco estranho , mas eu parei por aí.
hashchange
15

Este fez obras para mim:

function hasVerticalScroll(node){
    if(node == undefined){
        if(window.innerHeight){
            return document.body.offsetHeight> window.innerHeight;
        }
        else {
            return  document.documentElement.scrollHeight > 
                document.documentElement.offsetHeight ||
                document.body.scrollHeight>document.body.offsetHeight;
        }
    }
    else {
        return node.scrollHeight> node.offsetHeight;
    }
}

Para o corpo, basta usar hasVerticalScroll().

Kees C. Bakker
fonte
Esta é a única resposta neste tópico que funciona no meu Chrome
Nertan Lucian
clientHeighté preferível por offsetHeightaqui. Caso contrário, você pode ter uma borda grossa e retornar quando não houver barra de rolagem.
theicfire
12
var hasScrollbar = window.innerWidth > document.documentElement.clientWidth;
Roman Zaykovsky
fonte
Isso fez o trabalho, obrigado.
Vignesh Chinnaiyan
3

Estranhamente, nenhuma dessas soluções informa se uma página tem uma barra de rolagem vertical.

window.innerWidth - document.body.clientWidthfornecerá a largura da barra de rolagem. Isso deve funcionar em qualquer coisa IE9 + (não testada nos navegadores menores). (Ou, para responder estritamente à pergunta,!!(window.innerWidth - document.body.clientWidth)

Por quê? Digamos que você tenha uma página em que o conteúdo seja mais alto que a altura da janela e o usuário possa rolar para cima / baixo. Se você estiver usando o Chrome em um Mac sem o mouse conectado, o usuário não verá uma barra de rolagem. Conecte um mouse e uma barra de rolagem aparecerá. (Observe que esse comportamento pode ser substituído, mas esse é o AFAIK padrão).

David Gilbertson
fonte
A explicação do comportamento do Chrome-Mouse me ajudou a descobrir o que eu pensava ser um comportamento inconsistente. Obrigado!
theisof
2

Eu encontrei a solução vanila

var hasScrollbar = function() {
  // The Modern solution
  if (typeof window.innerWidth === 'number')
    return window.innerWidth > document.documentElement.clientWidth

  // rootElem for quirksmode
  var rootElem = document.documentElement || document.body

  // Check overflow style property on body for fauxscrollbars
  var overflowStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowStyle = rootElem.currentStyle.overflow

  overflowStyle = overflowStyle || window.getComputedStyle(rootElem, '').overflow

    // Also need to check the Y axis overflow
  var overflowYStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowYStyle = rootElem.currentStyle.overflowY

  overflowYStyle = overflowYStyle || window.getComputedStyle(rootElem, '').overflowY

  var contentOverflows = rootElem.scrollHeight > rootElem.clientHeight
  var overflowShown    = /^(visible|auto)$/.test(overflowStyle) || /^(visible|auto)$/.test(overflowYStyle)
  var alwaysShowScroll = overflowStyle === 'scroll' || overflowYStyle === 'scroll'

  return (contentOverflows && overflowShown) || (alwaysShowScroll)
}

Sergii Shvager
fonte
1
Não está funcionando no IE 11. window.innerWidth & document.documentElement.clientWidth são sempre os mesmos.
NLV
Corrigido. Essa mesma função também funciona para o IE 11. O problema era este - stackoverflow.com/questions/17045132/…
NLV
Eu testei isso no Chrome 65 e funciona. Mas quando eu o adapto para barras de rolagem horizontais, o resultado é estranho: se as barras de rolagem horizontal e vertical são exibidas, window.innerWidth > document.documentElement.clientWidthé verdade, mas window.innerHeight > document.documentElement.clientHeightnão é. Parece que foi o contrário neste caso. Não sou desenvolvedor de JS, só preciso dele para testes do Selenium. Sou grato por dicas.
Kriegaex
2
    <script>
    var scrollHeight = document.body.scrollHeight;
    var clientHeight = document.documentElement.clientHeight;
    var hasVerticalScrollbar = scrollHeight > clientHeight;

    alert(scrollHeight + " and " + clientHeight); //for checking / debugging.
    alert("hasVerticalScrollbar is " + hasVerticalScrollbar + "."); //for checking / debugging.
    </script>

Este lhe dirá se você tem uma barra de rolagem ou não. Incluí algumas informações que podem ajudar na depuração, que serão exibidas como um alerta JavaScript.

Coloque isso em uma tag de script, após a tag do corpo de fechamento.

Don D.
fonte
1

Escrevi uma versão atualizada da resposta de Kees C. Bakker:

const hasVerticalScroll = (node) => {
  if (!node) {
    if (window.innerHeight) {
      return document.body.offsetHeight > window.innerHeight
    }
    return (document.documentElement.scrollHeight > document.documentElement.offsetHeight)
      || (document.body.scrollHeight > document.body.offsetHeight)
  }
  return node.scrollHeight > node.offsetHeight
}

if (hasVerticalScroll(document.querySelector('body'))) {
  this.props.handleDisableDownScrollerButton()
}

A função retorna true ou false dependendo se a página possui uma barra de rolagem vertical ou não.

Por exemplo:

const hasVScroll = hasVerticalScroll(document.querySelector('body'))

if (hasVScroll) {
  console.log('HAS SCROLL', hasVScroll)
}
agm1984
fonte
1

eu uso

public windowHasScroll()
{
    return document.body.clientHeight > document.documentElement.clientHeight;
}
amoss
fonte
1

Basta comparar a largura do elemento raiz dos documentos (ou seja, elemento html) com a parte interna da janela:

if ((window.innerWidth - document.documentElement.clientWidth) >0) console.log('V-scrollbar active')

Se você também precisa saber a largura da barra de rolagem:

vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
Babak
fonte
0

Outras soluções não funcionaram em um dos meus projetos e acabei verificando a propriedade css do estouro

function haveScrollbar() {
    var style = window.getComputedStyle(document.body);
    return style["overflow-y"] != "hidden";
}

mas só funcionará se a barra de rolagem aparecer desaparecer, alterando o suporte. Não funcionará se o conteúdo for igual ou menor que a janela.

jcubic
fonte