Überprüfen Sie, ob das HTML-Element Bildlaufleisten enthält

113

Was ist der schnellste Weg, um zu überprüfen, ob ein Element Bildlaufleisten hat?

Eine Sache ist natürlich, zu überprüfen, ob das Element größer als sein Ansichtsfenster ist, was leicht durch Überprüfen dieser beiden Werte erreicht werden kann:

el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth

Das bedeutet aber nicht, dass es auch Bildlaufleisten gibt (so dass es tatsächlich von Menschen gescrollt werden kann).

Frage

Wie suche ich in einem 1- Cross-Browser und 2- Javascript (wie in keiner jQuery ) nach Bildlaufleisten ?

Nur Javascript, weil ich so wenig Overhead wie möglich benötige, weil ich einen sehr schnellen jQuery-Auswahlfilter schreiben möchte

// check for specific scrollbars
$(":scrollable(x/y/both)")

// check for ANY scrollbar
$(":scrollable")

Ich müsste wohl nach Stileinstellungen overflowsuchen, aber wie mache ich das browserübergreifend?

Zusätzliche Bearbeitung

Nicht nur overflowStileinstellungen. Zu überprüfen, ob ein Element eine Bildlaufleiste hat, ist nicht so trivial, wie es scheint. Die erste Formel, die ich oben geschrieben habe, funktioniert einwandfrei, wenn das Element keinen Rand hat, aber wenn dies der Fall ist (insbesondere wenn der Rand eine beträchtliche Breite hat), offsetkann die scrollBemaßung größer als die Bemaßung sein, das Element kann jedoch weiterhin scrollbar sein. Wir müssen tatsächlich Ränder von der offsetDimension subtrahieren , um das tatsächliche scrollbare Ansichtsfenster des Elements zu erhalten und dieses mit der scrollDimension zu vergleichen .

Zum späteren Nachschlagen

:scrollableDer jQuery-Auswahlfilter ist in meinem .scrollintoview()jQuery-Plugin enthalten. Den vollständigen Code finden Sie in meinem Blog-Beitrag, falls jemand ihn benötigt. Obwohl es nicht die eigentliche Lösung lieferte, half mir Soumyas Code erheblich, das Problem zu lösen. Es zeigte mir in die richtige Richtung.

Robert Koritnik
quelle

Antworten:

117

Ich habe das vor ein paar Wochen irgendwo gefunden. Es hat bei mir funktioniert.

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = div.scrollWidth > div.clientWidth;
var hasVerticalScrollbar = div.scrollHeight > div.clientHeight;

/* you'll get true/false */
jzhinga
quelle
12
Sie haben offensichtlich ein vereinfachtes Beispiel gehabt. Was ist, wenn Ihr Container darauf overflow:hiddengesetzt hat? Es würde überschüssigen Inhalt geben, aber es ist immer noch nicht scrollbar. Das Problem ist bei weitem nicht so einfach, wie es scheinen mag.
Robert Koritnik
7
Dies ist möglicherweise nicht die akzeptierte Lösung, aber es hat bei mir funktioniert. Ich bin mir nicht sicher, warum Sie es scrollen würden, wenn es versteckt ist.
Vol7ron
Dies ist möglicherweise nicht die akzeptierte Lösung, aber es hat bei mir funktioniert. Robert, konnten Sie in diesen Fällen nicht auch die CSS-Überlaufeigenschaft abrufen, um diese Fälle zu testen (z. B. div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))?
Vol7ron
7
Dies schlägt in vielen Fällen fehl. Wenn Ihr Element übergelaufen ist: sichtbar; Breite: 200px; Wenn Ihr Element ein untergeordnetes Element mit einer Breite von 500 Pixel hat, hat es keine Bildlaufleisten, sondern eine Bildlaufbreite von 500 Pixel und eine Clientbreite von 200 Pixel.
Joseph Lennox
1
Wenn ein Überlauf sichtbar oder ausgeblendet ist, gibt es normalerweise keine Bildlaufleisten.
Hubert Grzeskowiak
16

Versuchen:

Für vertikale Bildlaufleiste

el.scrollHeight> el.clientHeight

Für horizontale Bildlaufleiste

el.scrollWidth> el.clientWidth

Ich weiß, dass dies zumindest für IE8 und Firefox 3.6+ funktioniert.

Gary
quelle
2
Ich habe ja darauf hingewiesen, dass dies mir sagt, dass ein bestimmtes Element größer ist als es scheint, aber das bedeutet nicht, dass es Bildlaufleisten anzeigt. Es kann auch haben overflow:hiddenund es wäre nicht mehr scrollbar.
Robert Koritnik
1
Die Überprüfung mit clientHeight / clientWidth-Werten führt nicht zu guten Ergebnissen, da Elemente auch Rahmen haben können, die in dieser Kennzahl nicht enthalten sind. Überprüfen Sie meine Formel. Es funktioniert besser als deins.
Robert Koritnik
Dies gilt für die Verwendung von offsetHeight / offsetWidth zum Überprüfen von Bildlaufleisten anstelle von clientHeight / clientWidth. Vielen Dank für den Hinweis.
Gary
@RobertKoritnik - also überprüfe einfach, ob dieses bestimmte Element darauf ist overflow:hidden... dies ist meiner Meinung nach immer noch die richtige Antwort, da es die einfachste ist.
vsync
14

Dies mag ein wenig hackisch erscheinen (oder sein) , aber Sie können die Eigenschaften scrollTopund testen scrollLeft.

Wenn sie größer als 0 sind, wissen Sie, dass es Bildlaufleisten gibt. Wenn sie 0 sind, setzen Sie sie auf 1 und testen Sie sie erneut, um festzustellen, ob Sie ein Ergebnis von 1 erhalten. Setzen Sie sie dann wieder auf 0.

Beispiel: http://jsfiddle.net/MxpR6/1/

function hasScroll(el, direction) {
    direction = (direction === 'vertical') ? 'scrollTop' : 'scrollLeft';
    var result = !! el[direction];

    if (!result) {
        el[direction] = 1;
        result = !!el[direction];
        el[direction] = 0;
    }
    return result;
}

alert('vertical? ' + hasScroll(document.body, 'vertical'));
alert('horizontal? ' + hasScroll(document.body, 'horizontal'));

Ich glaube, es gibt eine andere Eigenschaft für IE, also werde ich in einer Minute damit aktualisieren.

BEARBEITEN: Es scheint, als ob der IE diese Eigenschaft unterstützt. (Ich kann den IE momentan nicht testen.)

http://msdn.microsoft.com/en-us/library/ms534618(VS.85).aspx

user113716
quelle
Es ist viel einfacher, nach Bildlaufleisten zu suchen, wenn Sie offsetHeightund vergleichen clientHeight. Letzteres ist immer um die Größe der Bildlaufleiste kleiner, wenn eine Bildlaufleiste vorhanden ist.
Robert Koritnik
@ Robert: Ich bin mir nicht sicher, ob es einfacher ist, aber ich sehe, wie es funktioniert. Dann gehe ich davon aus, dass ein Element overflow:scrollals scrollbar gemeldet werden soll, unabhängig davon, ob die Bildlaufleisten aktiviert sind oder nicht. Natürlich könnte meine Lösung Probleme haben, wenn ein Onscroll-Ereignis angehängt ist.
user113716
Nicht wirklich. Wenn Sie mein jQuery-Plugin überprüfen, muss ich einen tatsächlichen scrollbaren Vorfahren finden, da ich sonst kein Element in die Ansicht scrollen kann.
Robert Koritnik
8
@ RobertKoritnik Nicht wahr; Einige Browser verfügen möglicherweise über Bildlaufleisten, die die Breite nicht verringern. Zum Beispiel auf einem OS X. Oder Touch-Geräte.
daniel.gindi
1
immer falsch zurückgeben
Fatih Erol
14

Hier ist noch eine andere Lösung:

Wie einige Leute betonten, reicht es nicht aus, nur offsetHeight und scrollHeight zu vergleichen, da sie sich bei Elementen mit verstecktem Überlauf usw. unterscheiden, die noch keine Bildlaufleisten haben. Hier überprüfe ich auch, ob der Überlauf bei den berechneten Stilen für das Element scrollt oder automatisch ist:

var isScrollable = function(node) {
  var overflowY = window.getComputedStyle(node)['overflow-y'];
  var overflowX = window.getComputedStyle(node)['overflow-x'];
  return {
    vertical: (overflowY === 'scroll' || overflowY === 'auto') && node.scrollHeight > node.clientHeight,
    horizontal: (overflowX === 'scroll' || overflowX === 'auto') && node.scrollWidth > node.clientWidth,
  };
}
Lotif
quelle
Wenn ja, overflow*wird scrolles immer eine Bildlaufleiste geben, also denke ich, dass Sie wollen vertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeightusw. (dh entfernen Sie die Klammern, damit scroll*vs client*nur getestet wird, wenn dies der Fall overflow*ist auto). Ansonsten scheint dies die richtigste Lösung zu sein.
Jake
@Jake Wenn scrollHeight <clientHeight beim Scroll-Überlauf ist, werden die Bildlaufleisten angezeigt, aber deaktiviert (dh das Element kann nicht gescrollt werden). Ich denke, das hängt von der Anwendung ab. Ihre Änderung ist gültig, wenn Sie lediglich nach Bildlaufleisten suchen möchten, unabhängig vom Status. Als ich darauf kam, wollte ich Autoscroll für eine Komponente implementieren, daher ist es in diesem Fall nutzlos, Bildlaufleisten zu deaktivieren. Dies scheint auch bei dieser Frage der Fall zu sein (sie muss "von Menschen
gescrollt
6

Ich bin vielleicht etwas spät zur Party, aber ...

Ich glaube, Sie können Bildlaufleisten mit e.offsetWidth vs. e.clientWidth erkennen. Die versetzte Breite umfasst Rahmen und Bildlaufleisten, Auffüllung und Breite. Die Clientbreite umfasst Polsterung und Breite. Bitte sehen Sie:

https://developer.mozilla.org/en/DOM/element.offsetWidth (zweites Bild) https://developer.mozilla.org/en/DOM/element.clientWidth (zweites Bild)

Sie müssen überprüfen:

  1. Gibt an, ob für das Element der Überlauf auf Auto / Scroll (einschließlich Überlauf X / Y) eingestellt ist, wobei der berechnete / kaskadierte / aktuelle Stil verwendet wird.
  2. Wenn für das Element ein Überlauf auf Auto / Scroll eingestellt ist. Richten Sie die Offsetbreite und die Clientbreite ein.
  3. Wenn die clientWidth kleiner als der rechte Rand von offsetWidth - rechts ist (wieder gefunden durch den berechneten / kaskadierten / aktuellen Stil), wissen Sie, dass Sie eine Bildlaufleiste haben.

Machen Sie dasselbe für die Vertikale (Offset / ClientHeight).

IE7 meldet für einige Elemente eine clientHeight von 0 (ich habe nicht überprüft, warum), daher benötigen Sie immer die erste Überlaufprüfung.

Hoffe das hilft!


quelle
3

Es gibt verschiedene Probleme bei der Überprüfung des Vorhandenseins von Bildlaufleisten. Eines davon ist, dass Sie auf einem Mac keine sichtbare Bildlaufleiste haben, sodass beide oben genannten Lösungen keine genaue Antwort liefern.

Da das Rendern des Browsers nicht sehr häufig ist, können Sie den vorhandenen Bildlauf durch Ändern des Bildlaufs überprüfen und dann zurücksetzen:

const hasScrollBar = (element) => {
  const {scrollTop} = element;

  if(scrollTop > 0) {
    return true;
  }

  element.scrollTop += 10;

  if(scrollTop === element.scrollTop) {
    return false;
  }

  // undoing the change
  element.scrollTop = scrollTop;
  return true;
};

Hakobpogh
quelle
1

Ich habe hier nur rumgespielt, da (bisher) keine der oben genannten Lösungen für mich funktioniert hat. Ich habe einige Erfolge beim Vergleich der Scrollhöhe eines Div mit seiner Offsethöhe erzielt

var oh = $('#wrapDiv').get(0).offsetHeight;
var sh = $('#wrapDiv').get(0).scrollHeight;

Es scheint mir einen genauen Vergleich zu geben ... bis jetzt. Weiß jemand, ob dies legitim ist?

Michael
quelle
2
Ich denke, Sie wollen scrollHeight und clientHeight: stackoverflow.com/questions/4106538/…
Rich Remer
1

Für IE11 (Internet Explorer 11) musste ich die Logik ändern in:

// Subtract 3 (a small arbitrary number) to allow for IE reporting a difference of 1 when no scrollbar is present
var hasVerticalScrollbar = div.scrollHeight - 3 > div.clientHeight;

Dies liegt daran, dass der IE scrollHeight als 1 größer als clientHeight meldet, wenn keine Bildlaufleiste vorhanden ist, aber ungefähr 9 größer, wenn eine Bildlaufleiste vorhanden ist

danday74
quelle
0

Wenn Sie wissen möchten, ob eine Bildlaufleiste für die gesamte Webseite vorhanden ist und die vollständige Browserunterstützung verfügbar ist, können Sie Folgendes verwenden:

const hasScrollbar = document.body.scrollHeight > window.innerHeight

Es ist wichtig, window.innerHeightstatt zu verwenden, document.body.clientHeightda in einigen mobilen Browsern clientHeight nicht die Größe der Adressleiste erhält, scrollHeight jedoch, sodass Sie falsche Berechnungen erhalten.

Sebastian Hernandez
quelle
-5

Keine dieser Antworten ist richtig. Sie müssen dies verwenden:

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);
hamid
quelle
Dies wurde abgelehnt, weil es aus der akzeptierten Antwort von vor 6 Jahren kopiert / eingefügt wurde und Sie keine Klammern benötigen, um etwas in einen Booleschen Wert umzuwandeln.
Moto
-6

Fügen Sie ein 100% breites Element hinzu. Stellen Sie dann den Überlauf auf versteckt. Wenn sich der berechnete Stil des Elements (aus jQ) ändert, hatte das übergeordnete Element eine Bildlaufleiste.

EDIT: Anscheinend möchten Sie eine browserübergreifende Methode wie getComputedStyle . Versuchen:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}
Soumya
quelle
1
Wenn ich dafür bereits jQuery verwenden würde, würde ich lieber nur $(el).css("overflow/overflowX/overflowY")prüfen, ob es auf Auto oder Scrollen eingestellt ist . Ich möchte jedoch die Verwendung von jQuery vermeiden.
Robert Koritnik
16
Die CSS-Stile sagen Ihnen NICHT, ob ein Element Bildlaufleisten hat oder nicht . Nur ob es Bildlaufleisten haben kann oder nicht . Vielleicht eine browserübergreifende Methode zur Bestimmung der Breite des inneren Elements finden?
Soumya
@ Soumya92: Der Größenvergleich zwischen scrollbarer und tatsächlicher Größe ist trivial und ich habe ihn oben geschrieben ... Alles, was ich jetzt überprüfen muss, ist die aktuelle Überlaufeinstellung für ein bestimmtes Element.
Robert Koritnik
@ Soumya92: genau das brauche ich. Es kann auch sehr stark vereinfacht werden, indem Coalesce verwendet wirdcomputedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik
Noch etwas: Wie browserübergreifend ist das? Welche Browser werden davon unterstützt?
Robert Koritnik