Controlla se l'elemento HTML ha barre di scorrimento


113

Qual è il modo più veloce per verificare se un elemento ha barre di scorrimento?

Una cosa ovviamente è controllare se l'elemento è più grande della sua finestra, che può essere facilmente fatto controllando questi due valori:

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

ma questo non significa che abbia anche le barre di scorrimento (quindi può effettivamente essere fatto scorrere dagli umani).

Domanda

Come posso verificare la presenza di barre di scorrimento in 1 browser incrociato e 2 solo javascript (come in nessun jQuery )?

Solo Javascript, perché ho bisogno del minor overhead possibile, perché mi piacerebbe scrivere un filtro selettore jQuery molto veloce

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

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

Suppongo che dovrei controllare overflow impostazioni di stile, ma come posso farlo in modo cross browser?

Modifica aggiuntiva

Non solo overflowimpostazioni di stile. Controllare se un elemento ha una barra di scorrimento non è così banale come sembra. La prima formula che ho scritto sopra funziona bene quando l'elemento non ha un bordo, ma quando lo fa (specialmente quando il bordo è di larghezza considerevole), la offsetdimensione può essere più grande della scrolldimensione ma l'elemento può ancora essere scorrevole. In realtà dobbiamo sottrarre i bordi dalla offsetdimensione per ottenere la visualizzazione scorrevole effettiva dell'elemento e confrontarla conscroll dimensione.

Per riferimento futuro

:scrollableIl filtro selettore jQuery è incluso nel mio .scrollintoview()plugin jQuery. Il codice completo può essere trovato nel mio post sul blog se qualcuno ne ha bisogno. Anche se non ha fornito la soluzione effettiva, il codice di Soumya mi ha notevolmente aiutato a risolvere il problema. Mi ha indirizzato nella giusta direzione.

Risposte:


118

L'ho trovato da qualche parte un paio di settimane fa. Ha funzionato per me.

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

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

/* you'll get true/false */

12
Ovviamente hai avuto un esempio semplificato. E se il tuo contenitore fosse overflow:hiddenposizionato su di esso? Ci sarebbe un contenuto in eccesso ma non è ancora scorrevole. Il problema non è di gran lunga così semplice come potrebbe sembrare.
Robert Koritnik

7
Questa potrebbe non essere la soluzione accettata, ma per me ha funzionato. Non sono sicuro del motivo per cui lo faresti scorrere se è nascosto.
vol7ron

Questa potrebbe non essere la soluzione accettata, ma per me ha funzionato. Robert, per quei casi, non potresti anche recuperare la proprietà CSS overflow per testare quei casi (ad esempio div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))?
vol7ron

7
Questo fallisce in molti casi. Se il tuo elemento ha un overflow: visibile; larghezza: 200 px; e ha un figlio con una larghezza di 500 px, il tuo elemento non ha barre di scorrimento ma ha una Larghezza di scorrimento di 500 px e una Larghezza client di 200 px.
Joseph Lennox

1
Se l'overflow è visibile o nascosto, di solito non ci sono barre di scorrimento.
Hubert Grzeskowiak

16

Provare:

Per barra di scorrimento verticale

el.scrollHeight> el.clientHeight

Per barra di scorrimento orizzontale

el.scrollWidth> el.clientWidth

So che funziona almeno per IE8 e Firefox 3.6+.


2
Ho fatto notare che sì che questo mi dice che un certo elemento è più grande di quanto sembri, ma ciò non significa che visualizzi le barre di scorrimento. Può anche avere overflow:hiddene non sarebbe più scorrevole.
Robert Koritnik

1
E il controllo con i valori clientHeight / clientWidth non dà buoni risultati, perché anche gli elementi possono avere bordi, che non sono inclusi in questa misura. Controlla la mia formula. Funziona meglio del tuo.
Robert Koritnik

Questo è vero riguardo all'uso di offsetHeight / offsetWidth per il controllo delle barre di scorrimento invece di clientHeight / clientWidth. Grazie per la segnalazione.
Gary

@RobertKoritnik - quindi controlla se quell'elemento specifico ha overflow:hiddensu di esso ... questa è ancora la risposta corretta secondo me, poiché è la più semplice.
vsync

14

Questo può sembrare (o essere) un po 'hacker, ma potresti testare le proprietà scrollTope scrollLeft.

Se sono maggiori di 0, sai che ci sono barre di scorrimento. Se sono 0, impostali su 1 e provali di nuovo per vedere se ottieni un risultato di 1. Quindi reimpostali su 0.

Esempio: 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'));

Credo che ci sia una proprietà diversa per IE, quindi la aggiornerò tra un minuto.

MODIFICARE: appare come se IE potesse supportare questa proprietà. (Non posso testare IE in questo momento.)

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


È molto più facile controllare le barre di scorrimento se si confrontano offsetHeighte clientHeight. Quest'ultimo è sempre più piccolo della dimensione della barra di scorrimento quando è presente la barra di scorrimento.
Robert Koritnik

@ Robert: Non sono sicuro che sia più facile, ma vedo come funziona. Quindi presumo che se un elemento ha overflow:scroll, vuoi che sia segnalato come scorrevole indipendentemente dal fatto che le barre di scorrimento siano abilitate o meno. Ovviamente la mia soluzione potrebbe avere problemi se è allegato un evento onscroll.
user113716

Non proprio. Se controlli il mio plugin jQuery devo trovare l'antenato scorrevole effettivo altrimenti non posso scorrere un elemento nella visualizzazione.
Robert Koritnik

8
@RobertKoritnik Non è vero; alcuni browser potrebbero avere barre di scorrimento che non riducono la larghezza. Su un OS X per esempio. Oppure tocca i dispositivi.
daniel.gindi

1
restituire sempre false
Fatih Erol

14

Ecco un'altra soluzione:

Come alcune persone hanno sottolineato, il semplice confronto tra offsetHeight e scrollHeight non è sufficiente poiché differiscono su elementi con overflow nascosto, ecc., Che ancora non hanno le barre di scorrimento. Quindi qui sto anche controllando se l'overflow è scroll o auto sugli stili calcolati per l'elemento:

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

Se overflow*è scrollci sarà sempre una barra di scorrimento, quindi penso che tu voglia vertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeight, ecc. (Cioè rimuovi le parentesi così scroll*vs client*viene testato solo quando overflow*è auto). Altrimenti questa sembra essere la soluzione più corretta.
Jake

@Jake Se scrollHeight <clientHeight su scroll overflow, le barre di scorrimento saranno lì ma saranno disabilitate (cioè l'elemento non è scorrevole). Quindi penso che dipenda dall'applicazione. La tua modifica è valida se desideri semplicemente verificare la presenza di barre di scorrimento, non importa lo stato. Per me, quando ho pensato a questo, stavo cercando di implementare lo scorrimento automatico per un componente, quindi avere le barre di scorrimento disabilitate è inutile in quel caso. Questo sembra essere il caso anche per questa domanda (deve "essere fatta scorrere dagli umani")
lotif

6

Forse sono un po 'in ritardo per la festa, ma ...

Credo che tu possa rilevare le barre di scorrimento con e.offsetWidth rispetto a e.clientWidth. La larghezza dell'offset include bordi e barre di scorrimento, spaziatura interna e larghezza. La larghezza del cliente include imbottitura e larghezza. Perfavore guarda:

https://developer.mozilla.org/en/DOM/element.offsetWidth (seconda immagine) https://developer.mozilla.org/en/DOM/element.clientWidth (seconda immagine)

Devi controllare:

  1. Indica se l'elemento ha o meno overflow impostato su auto / scroll (incluso overflowX / Y) utilizzando lo stile calcolato / a cascata / corrente.
  2. Se l'elemento ha overflow impostato su auto / scroll. Stabilire offsetWidth e clientWidth.
  3. Se clientWidth è inferiore a offsetWidth - bordo destro (trovato di nuovo attraverso lo stile calcolato / a cascata / corrente), allora sai di avere una barra di scorrimento.

Fai lo stesso per la verticale (offset / clientHeight).

IE7 riporta un clientHeight di 0 per alcuni elementi (non ho verificato perché), quindi è sempre necessario il primo controllo di overflow.

Spero che questo ti aiuti!


3

Ci sono diversi problemi in caso di verifica dell'esistenza delle barre di scorrimento, uno dei quali è che in mac non hai alcuna barra di scorrimento visibile, quindi entrambe le soluzioni sopra non ti darebbero una risposta accurata.

Quindi, poiché il rendering del browser non è molto frequente, puoi controllare lo scorrimento con la modifica dello scorrimento e quindi reimpostarlo:

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


1

Sto solo scherzando qui perché nessuna delle soluzioni di cui sopra ha funzionato per me (finora). Ho riscontrato un certo successo confrontando l'altezza di scorrimento di un Div con il suo offsetHeight

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

Sembra che mi dia un accurato confronto ... finora. Qualcuno sa se questo è legittimo?


2
Penso che si desidera scrollHeight e clientHeight: stackoverflow.com/questions/4106538/...
ricca Remer

1

Per IE11 (Internet Explorer 11) ho dovuto modificare la logica 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;

Questo perché IE riporta scrollHeight come 1 più grande di clientHeight quando non è presente alcuna barra di scorrimento ma circa 9 più grande quando è presente una barra di scorrimento


0

Se hai bisogno di sapere se è presente una barra di scorrimento per l'intera pagina web e con il supporto completo del browser puoi usare questo:

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

È importante da usare al window.innerHeightposto di document.body.clientHeightperché in alcuni browser mobili clientHeight non otterrà le dimensioni della barra degli indirizzi ma scrollHeight lo farà, quindi si ottengono calcoli sbagliati.


-5

nessuna di queste risposte è corretta. devi usare questo:

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

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);

Questo è stato svuotato perché è stato copiato / incollato dalla risposta accettata di 6 anni fa e non hai bisogno delle parentesi per trasformare qualcosa in un booleano.
moto

-6

Aggiungi un elemento largo 100% al suo interno. Quindi imposta l'overflow su nascosto. Se lo stile calcolato dell'elemento (da jQ) cambia, il genitore aveva una barra di scorrimento.

EDIT: Sembra che tu voglia un metodo cross browser come getComputedStyle . Provare:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}

1
Se usassi già jQuery per questo, preferirei solo fare $(el).css("overflow/overflowX/overflowY")e vedere se è impostato su automatico o scorrimento . Ma vorrei evitare di usare jQuery.
Robert Koritnik

16
Gli stili CSS NON ti diranno se un elemento ha o meno barre di scorrimento. Solo se sia o non può avere barre di scorrimento. Forse trovare un metodo cross browser per determinare la larghezza dell'elemento interno?
Soumya

@ Soumya92: Il confronto delle dimensioni tra le dimensioni scorrevoli e quelle effettive è banale e l'ho scritto sopra ... Tutto quello che devo controllare ora è l'impostazione corrente di overflow su un particolare elemento.
Robert Koritnik

@ Soumya92: è esattamente quello che mi serve. Può anche essere molto semplificato usando il coalescecomputedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik

Un'altra cosa: come funziona il cross browser? Quali browser sono supportati da questo?
Robert Koritnik
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.