Erkennen, ob eine Seite eine vertikale Bildlaufleiste hat?


121

Ich möchte nur ein einfaches JQ / JS, um zu überprüfen, ob die aktuelle Seite / das aktuelle Fenster (kein bestimmtes Element) eine vertikale Bildlaufleiste hat.

Googeln gibt mir Dinge, die nur für diese Grundfunktion zu komplex erscheinen.

Wie kann das gemacht werden?

Antworten:


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, aber der Genauigkeit halber wird nur geprüft, ob der Inhalt weiter als das Ansichtsfenster erweitert wird. Wenn die overflowEigenschaft der bodyeinzustellen ist hiddenirgendwo entlang der Linie, wird es nicht funktionieren. Das Verstecken an einem Körper ist jedoch äußerst selten.
Pekka

4
Dies funktioniert nicht, wenn die Körperhöhe mit der Fensterhöhe übereinstimmt. Wenn die Dokumenthöhe genau mit dem Ansichtsfenster übereinstimmt, wird eine horizontale Bildlaufleiste hinzugefügt . Es wird vert erzwingen. Bildlaufleiste, aber Höhe von doc / body / window sind gleich; Es wird KEINE "vertikale Bildlaufleiste" alarmieren, selbst wenn es eine gibt.
Hören Sie auf, Monica Cellio

2
Ich dachte nur, ich würde erwähnen, dass ich $(document)stattdessen verwenden $("body")musste. Dies funktionierte für mich, wenn der Körper dies nicht tat (ich habe einen absolut positionierten Behälter mit einem Seitenverhältnis von Breite / Höhe)
am_

1
Ich habe eine Berichtsseite im Chrome-Browser, auf der zunächst eine Bildlaufleiste angezeigt wird und innerhalb von Millisekunden verschwindet, was wie ein Browserverhalten aussieht, da ich sie nicht programmiert habe. Also diese Funktion gibt in meinem Fall immer true zurück.
Dush

@TiuTalk für mich $ ("body"). Height () & $ (window) .height () gibt den gleichen Wert an, stattdessen verwende ich $ (document) .height ()> $ (window) .height (), für das es funktioniert mich.
SarangK

77

Versuche dies:

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

Dies zeigt Ihnen jedoch nur an, ob die vertikale scrollHeight größer als die Höhe des sichtbaren Inhalts ist. Die hasVScrollVariable enthält true oder false.

Wenn Sie eine gründlichere Überprüfung durchführen müssen, fügen Sie dem obigen Code Folgendes hinzu:

// 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 Schön! Und mit dem notwendigen berechneten Stil (an diesem Punkt habe ich beschlossen, mich nicht auf diese Frage
Pekka

lol yeah Ich habe überlegt, ob ich mir die Mühe machen soll, es zu schreiben, weil es in vielen Fällen nicht benötigt wird.
Andy E

1
Dies führt dazu, dass hasVScroll immer dann wahr ist, wenn overflowY 'sichtbar' ist, unabhängig davon, ob die scrollHeight größer als die clientHeight ist. Vielleicht hast du gemeint cStyle.overflow === 'scroll'?
BT

5
Der obige Code funktioniert nicht. Browser: Chrome 56. URL
Sebastien Lorber

1
@BT cStyle.overflow == "visible" kann Bildlaufleisten anzeigen , wenn das Element das ist document.body. Aber es sollte sein (hasVScroll && cStyle.overflow == "sichtbar" && element.nodeName == "BODY"). Außerdem muss überprüft werden, cStyle.overflow === 'scroll'wie Sie darauf hinweisen.
mseifert

44

Ich habe die vorherige Antwort ausprobiert und scheint nicht mit $ ("body") zu arbeiten. Height () repräsentiert nicht unbedingt die gesamte HTML-Höhe.

Ich habe die Lösung wie folgt korrigiert:

// 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

Lassen Sie uns diese Frage von den Toten zurückbringen;) Es gibt einen Grund, warum Google Ihnen keine einfache Lösung bietet. Sonderfälle und Browser-Macken wirken sich auf die Berechnung aus und sind nicht so trivial, wie es scheint.

Leider gibt es bisher Probleme mit den hier beschriebenen Lösungen. Ich möchte sie überhaupt nicht herabsetzen - sie sind gute Ausgangspunkte und berühren alle Schlüsseleigenschaften, die für einen robusteren Ansatz erforderlich sind. Aber ich würde nicht empfehlen, den Code aus einer der anderen Antworten zu kopieren und einzufügen, weil

  • Sie erfassen den Effekt von positionierten Inhalten nicht auf eine Weise, die zuverlässig und browserübergreifend ist. Die Antworten, die auf der Körpergröße basieren, verfehlen dies vollständig (der Körper ist nicht das versetzte übergeordnete Element eines solchen Inhalts, es sei denn, er ist selbst positioniert). Und diese Antworten überprüfen $( document ).width()und .height()fallen der fehlerhaften Erkennung der Dokumentgröße durch jQuery zum Opfer .
  • Unter Berufung auf window.innerWidth, wenn der Browser unterstützt, Ihr Code macht Scrollbalken in mobilen Browsern erkennen ausfallen, wobei die Breite der Bildlaufleiste ist in der Regel 0. Sie sind nur vorübergehend als Overlay angezeigt und nehmen nicht Raum in dem Dokument . Auf diese Weise wird auch das Zoomen auf dem Handy zum Problem (lange Geschichte).
  • Die Erkennung kann deaktiviert werden, wenn Benutzer den Überlauf des Elements htmlund des bodyElements explizit auf nicht standardmäßige Werte setzen (was dann passiert, ist ein wenig kompliziert - siehe diese Beschreibung ).
  • In den meisten Antworten werden Körperpolster, Ränder oder Ränder nicht erkannt und verzerren die Ergebnisse.

Ich habe mehr Zeit damit verbracht, als ich mir vorgestellt hätte, eine Lösung zu finden, die "einfach funktioniert" (Husten). Der Algorithmus, den ich mir ausgedacht habe , ist jetzt Teil eines Plugins, jQuery.isInView , das eine .hasScrollbarMethode verfügbar macht . Schauen Sie sich die Quelle an, wenn Sie möchten.

In einem Szenario, in dem Sie die volle Kontrolle über die Seite haben und sich nicht mit unbekanntem CSS befassen müssen, kann die Verwendung eines Plugins übertrieben sein - schließlich wissen Sie, welche Randfälle zutreffen und welche nicht. Wenn Sie jedoch zuverlässige Ergebnisse in einer unbekannten Umgebung benötigen, sind die hier beschriebenen Lösungen meiner Meinung nach nicht ausreichend. Sie sind besser dran, wenn Sie ein gut getestetes Plugin verwenden - meins oder sonst jemand.


Vielen Dank. Ziemlich kompliziert! Wenn Sie nicht abwärtskompatibel sein möchten / müssen, gibt es vielleicht eine einfachere Lösung für HTML5-Browser? Ich meine, vielleicht waren die Browser-Codierer / w3c nett genug, um uns nur zu sagen, ob es Bildlaufleisten gibt oder nicht? ;-)
Leo

1
@ Leo Nicht das ich weiß. Nun, es gibt ein window.scrollbarsObjekt, das eine einzige Eigenschaft hat visible. Klingt vielversprechend, ist es aber nicht. Es wird im IE, einschließlich IE11, nicht unterstützt. Und es sagt Ihnen nur, dass es eine Bildlaufleiste gibt - aber nicht welche. Siehe die Testseite hier .
Hashchange

Danke @hashchange. Es klingt unglaublich dumm, dass es nur sagt, ob es eine Bildlaufleiste gibt, also denke ich, dass es nur eine Art Test ist. Ein bisschen vielversprechend. ;-);
Leo

1
@ BT Ok, großartig. Jetzt lass mich dich zum Eingang des Kaninchenbaues führen;) Hier ist eine Demo, bei der der Inhalt nicht ausreicht, um das Fenster zu füllen. Ihre Erkennung funktioniert in FF, schlägt jedoch in Chrome fehl. Und hier ist eine weitere Demo, in der ein positioniertes Element weit unten auf der Seite platziert wird. Ihre Erkennung funktioniert in Chrome, schlägt jedoch in FF fehl.
Hashwechsel

1
@BT Und ich denke, wir können in eine Reihe seltsamer Fehlermodi geraten, wenn wir anfangen, mit Überlaufeinstellungen zu spielen, weil ihr Verhalten etwas seltsam ist , aber ich habe genau dort aufgehört.
Hashchange

15

Dieser hat für mich funktioniert:

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

Für den Körper einfach verwenden hasVerticalScroll().


Dies ist die einzige Antwort in diesem Thread, die auf meinem Chrome
funktioniert

clientHeightist hier vorzuziehen offsetHeight. Andernfalls können Sie einen dicken Rand haben und zurückgeben, dass dort keine Bildlaufleiste vorhanden ist.
Theicfire


3

Seltsamerweise sagt Ihnen keine dieser Lösungen, ob eine Seite eine vertikale Bildlaufleiste hat.

window.innerWidth - document.body.clientWidthgibt Ihnen die Breite der Bildlaufleiste. Dies sollte in jedem IE9 + funktionieren (nicht in den kleineren Browsern getestet). (Oder um die Frage streng zu beantworten,!!(window.innerWidth - document.body.clientWidth)

Warum? Angenommen, Sie haben eine Seite, auf der der Inhalt größer als die Fensterhöhe ist und der Benutzer nach oben / unten scrollen kann. Wenn Sie Chrome auf einem Mac ohne angeschlossene Maus verwenden, wird dem Benutzer keine Bildlaufleiste angezeigt. Schließen Sie eine Maus an und eine Bildlaufleiste wird angezeigt. (Beachten Sie, dass dieses Verhalten überschrieben werden kann, dies ist jedoch die Standard-AFAIK.)


Die Erklärung des Verhaltens von Chrome-Mouse half mir herauszufinden, was ich für inkonsistentes Verhalten hielt. Vielen Dank!
Theisof

2

Ich habe Vanila-Lösung gefunden

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
Funktioniert nicht in IE 11. window.innerWidth & document.documentElement.clientWidth sind immer gleich.
NLV

Behoben. Diese Funktion funktioniert auch für IE 11. Das Problem war folgendes: stackoverflow.com/questions/17045132/…
NLV

Ich habe dies in Chrome 65 getestet und es funktioniert. Aber wenn ich es für horizontale Bildlaufleisten anpasse, ist das Ergebnis seltsam: Wenn sowohl horizontale als auch vertikale Bildlaufleisten angezeigt werden, window.innerWidth > document.documentElement.clientWidthist dies wahr, aber window.innerHeight > document.documentElement.clientHeightnicht. Es sieht so aus, als wäre es in diesem Fall umgekehrt. Ich bin kein JS-Entwickler, ich brauche es nur für Selen-Tests. Ich bin dankbar für Hinweise.
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>

Dieser sagt Ihnen, ob Sie eine Bildlaufleiste haben oder nicht. Ich habe einige Informationen eingefügt, die beim Debuggen hilfreich sein können und als JavaScript-Warnung angezeigt werden.

Fügen Sie dies nach dem schließenden Body-Tag in ein Skript-Tag ein.


1

Ich habe eine aktualisierte Version von Kees C. Bakkers Antwort geschrieben:

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

Die Funktion gibt true oder false zurück, je nachdem, ob die Seite eine vertikale Bildlaufleiste hat oder nicht.

Beispielsweise:

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

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

1

ich benutze

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

1

Vergleichen Sie einfach die Breite des Dokumentenstammelements (dh des HTML-Elements) mit dem inneren Teil des Fensters:

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

Wenn Sie auch die Breite der Bildlaufleiste kennen müssen:

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

0

Andere Lösungen haben in einem meiner Projekte nicht funktioniert und ich habe am Ende die Überlauf-CSS-Eigenschaft überprüft

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

Es funktioniert jedoch nur, wenn die Bildlaufleiste durch Ändern der Requisite ausgeblendet wird. Es funktioniert nicht, wenn der Inhalt gleich oder kleiner als das Fenster ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.