Détecter si une page a une barre de défilement verticale?


121

Je veux juste un simple JQ / JS pour vérifier si la page / fenêtre actuelle (pas un élément particulier) a une barre de défilement verticale.

Googler me donne des choses qui semblent trop complexes pour cette fonctionnalité de base.

Comment cela peut-il être fait?

Réponses:


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:<");
    }
});

14
+1 mais par souci d'exactitude, cela vérifie uniquement si le contenu se développe au-delà de la fenêtre. Si la overflowpropriété de bodyest définie sur hiddenquelque part le long de la ligne, cela ne fonctionnera pas. La mise cachée sur un corps est cependant extrêmement rare.
Pekka

4
Cela ne fonctionne pas si la hauteur du corps correspond à la hauteur de la fenêtre, ce qui est le cas si la hauteur du document correspond exactement à la fenêtre, puis une barre de défilement horizontale est ajoutée . Cela forcera vert. la barre de défilement mais la hauteur de doc / corps / fenêtre est la même; il n'alertera PAS "la barre de défilement verticale" même s'il y en a une.
Arrêtez de calomnier Monica Cellio

2
Je pensais juste que je devais mentionner que je devais utiliser à la $(document)place de $("body"), cela a fonctionné pour moi quand le corps ne l'a pas fait (j'ai un conteneur absolu avec un rapport hauteur / largeur sur la largeur / hauteur)
am_

1
J'ai une page de rapport sur le navigateur Chrome où elle affiche initialement une barre de défilement et disparaît en quelques millisecondes, ce qui ressemble à un comportement de navigateur puisque je ne l'ai pas programmée. Donc, cette fonction retourne toujours vrai dans mon cas ..
Dush

@TiuTalk pour moi $ ("body"). Height () & $ (window) .height () donne la même valeur, à la place j'utilise $ (document) .height ()> $ (window) .height () cela fonctionne pour moi.
SarangK

77

essaye ça:

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

Cela vous dira seulement si la hauteur de défilement verticale est plus grande que la hauteur du contenu visible, cependant. La hasVScrollvariable contiendra vrai ou faux.

Si vous devez effectuer une vérification plus approfondie, ajoutez ce qui suit au code ci-dessus:

// 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");

1
+1 Bien! Et avec le style calculé nécessaire (c'est à ce moment-là que j'ai décidé de ne pas m'impliquer dans cette question;)
Pekka

lol ouais, je me demandais si je devais faire l'effort supplémentaire de l'écrire parce que dans de nombreux cas, ce n'est pas nécessaire.
Andy E

1
Il en résulte que hasVScroll est vrai chaque fois que overflowY est «visible», que scrollHeight soit supérieur ou non à clientHeight. Peut-être que vous vouliez dire cStyle.overflow === 'scroll'?
BT

5
Le code ci-dessus ne fonctionne pas. Navigateur: Chrome 56. Url: news.greylock.com
Sebastien Lorber

1
@BT cStyle.overflow == "visible" peut afficher des barres de défilement lorsque l'élément est le document.body. Mais il devrait l'être (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY"). De plus, il doit vérifier cStyle.overflow === 'scroll'que vous le signalez.
mseifert

44

J'ai essayé la réponse précédente et ne semble pas fonctionner le $ ("body"). Height () ne représente pas nécessairement toute la hauteur html.

J'ai corrigé la solution comme suit:

// 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:<"); 
} 

18

Ramenons cette question d'entre les morts;) Il y a une raison pour laquelle Google ne vous donne pas de solution simple. Les cas particuliers et les bizarreries du navigateur affectent le calcul, et ce n'est pas aussi trivial qu'il y paraît.

Malheureusement, il y a des problèmes avec les solutions décrites ici jusqu'à présent. Je ne veux pas du tout les dénigrer - ce sont d'excellents points de départ et touchent toutes les propriétés clés nécessaires pour une approche plus robuste. Mais je ne recommanderais pas de copier et coller le code de l'une des autres réponses car

  • ils ne capturent pas l'effet du contenu positionné d'une manière fiable entre les navigateurs. Les réponses basées sur la taille du corps manquent complètement cela (le corps n'est pas le parent décalé d'un tel contenu, sauf s'il est positionné lui-même). Et ces réponses vérifient $( document ).width()et .height()sont la proie de la détection boguée de jQuery de la taille du document .
  • Reposant sur window.innerWidth , si le navigateur le prend en charge, empêche votre code de détecter les barres de défilement dans les navigateurs mobiles, où la largeur de la barre de défilement est généralement de 0. Elles sont simplement affichées temporairement en superposition et ne prennent pas de place dans le document . Le zoom sur mobile devient également un problème de cette façon (longue histoire).
  • La détection peut être désactivée lorsque les gens définissent explicitement le débordement de l' élément htmlet bodysur des valeurs non par défaut (ce qui se passe alors est un peu compliqué - voir cette description ).
  • Dans la plupart des réponses, le rembourrage du corps, les bordures ou les marges ne sont pas détectés et déforment les résultats.

J'ai passé plus de temps que je ne l'aurais imaginé à trouver une solution qui "fonctionne juste" (toux). L'algorithme que j'ai mis au point fait maintenant partie d'un plugin, jQuery.isInView , qui expose une .hasScrollbarméthode . Jetez un œil à la source si vous le souhaitez.

Dans un scénario où vous avez le contrôle total de la page et que vous n'avez pas à gérer de CSS inconnu, l'utilisation d'un plugin peut être exagérée - après tout, vous savez quels cas limites s'appliquent et lesquels ne le sont pas. Cependant, si vous avez besoin de résultats fiables dans un environnement inconnu, je ne pense pas que les solutions décrites ici suffiront. Vous feriez mieux d'utiliser un plugin bien testé - le mien ou n'importe qui d'autre.


Merci. Un peu compliqué! Si vous ne voulez pas / devez être rétrocompatible, y a-t-il peut-être une solution plus simple pour les navigateurs html5? Je veux dire peut-être que les codeurs de navigateur / w3c ont été assez gentils pour simplement nous dire s'il y a des barres de défilement ou non sur un élément? ;-)
Leo

1
@Leo Pas que je sache. Eh bien, il y a un window.scrollbarsobjet qui a une seule propriété, visible. Cela semble prometteur mais ne l'est pas. Il n'est pas pris en charge dans IE, y compris IE11. Et cela vous indique simplement qu'il y a une barre de défilement - mais pas laquelle. Voir la page de test ici .
hashchange

Merci @hashchange. Cela semble incroyablement stupide que cela indique simplement s'il y a une barre de défilement, donc je suppose que ce n'est encore qu'une sorte de test. Un peu prometteur cependant. ;-)
Leo

1
@BT Ok, super. Maintenant, laissez-moi vous conduire à l'entrée du terrier du lapin;) Voici une démo où le contenu ne suffit pas à remplir la fenêtre. Votre détection fonctionne dans FF mais échoue dans Chrome. Et voici une autre démo où un élément positionné est placé loin en bas de la page. Votre détection fonctionne dans Chrome mais échoue dans FF.
hashchange

1
@BT Et je suppose que nous pouvons entrer dans un tas de modes d'échec étranges lorsque nous commençons à jouer avec les paramètres de débordement parce que leur comportement est un peu étrange , mais je me suis arrêté là.
hashchange

15

Celui-ci a fonctionné pour moi:

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;
    }
}

Pour le corps, il suffit d'utiliser hasVerticalScroll().


C'est la seule réponse dans ce fil qui fonctionne sur mon Chrome
Nertan Lucian

clientHeightest préférable offsetHeightici. Sinon, vous pouvez avoir une bordure épaisse, et retourner il n'y a pas de barre de défilement quand il y en a.
theicfire


3

Curieusement, aucune de ces solutions ne vous indique si une page a une barre de défilement verticale.

window.innerWidth - document.body.clientWidthvous donnera la largeur de la barre de défilement. Cela devrait fonctionner dans tout ce qui concerne IE9 + (non testé dans les navigateurs inférieurs). (Ou pour répondre strictement à la question,!!(window.innerWidth - document.body.clientWidth)

Pourquoi? Disons que vous avez une page où le contenu est plus haut que la hauteur de la fenêtre et que l'utilisateur peut faire défiler vers le haut / bas. Si vous utilisez Chrome sur un Mac sans souris branchée, l'utilisateur ne verra pas de barre de défilement. Branchez une souris et une barre de défilement apparaîtra. (Notez que ce comportement peut être remplacé, mais c'est l'AFAIK par défaut).


L'explication du comportement de la souris Chrome m'a aidé à comprendre ce que je pensais être un comportement incohérent. Merci!
date du

2

J'ai trouvé la solution de vanille

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)
}


1
Ne fonctionne pas dans IE 11. window.innerWidth et document.documentElement.clientWidth sont toujours les mêmes.
NLV

Corrigé. Cette même fonction fonctionne également pour IE 11. Le problème était le suivant - stackoverflow.com/questions/17045132/…
NLV

J'ai testé cela dans Chrome 65 et cela fonctionne. Mais quand je l'adapte pour les barres de défilement horizontales, le résultat est étrange: si les barres de défilement horizontales et verticales sont affichées, window.innerWidth > document.documentElement.clientWidthc'est vrai, mais window.innerHeight > document.documentElement.clientHeightne l'est pas. Il semble que ce soit l'inverse dans ce cas. Je ne suis pas un développeur JS, j'en ai juste besoin pour les tests Selenium. Je suis reconnaissant pour les indices.
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>

Celui-ci vous dira si vous avez une barre de défilement ou non. J'ai inclus des informations qui peuvent aider au débogage, qui s'afficheront sous forme d'alerte JavaScript.

Mettez ceci dans une balise de script, après la balise de fermeture du corps.


1

J'ai écrit une version mise à jour de la réponse 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()
}

La fonction renvoie vrai ou faux selon que la page a une barre de défilement verticale ou non.

Par exemple:

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

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

1

j'utilise

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

1

Comparez simplement la largeur de l'élément racine des documents (c'est-à-dire l'élément html) à la partie intérieure de la fenêtre:

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

Si vous avez également besoin de connaître la largeur de la barre de défilement:

vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

0

D'autres solutions n'ont pas fonctionné dans l'un de mes projets et j'ai fini par vérifier la propriété css de débordement

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

mais cela ne fonctionnera que si la barre de défilement apparaît disparaître en changeant l'accessoire, cela ne fonctionnera pas si le contenu est égal ou inférieur à la fenêtre.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.