HTML要素にスクロールバーがあるかどうかを確認する


113

要素にスクロールバーがあるかどうかを確認する最も速い方法は何ですか?

もちろん、要素がそのビューポートより大きいかどうかを確認することは、次の2つの値を確認することで簡単に実行できます。

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

しかし、それはそれが同様にスクロールバーを持っていることを意味しません(したがって、実際に人間がスクロールすることができます)。

質問

1つのクロスブラウザーで2つの JavaScriptのみ(jQueryない場合と同様)でスクロールバーを確認するにはどうすればよいですか?

Javascriptのみ。非常に高速なjQueryセレクターフィルターを作成したいので、可能な限り小さなオーバーヘッドが必要です。

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

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

overflowスタイル設定を確認する必要があると思いますが、クロスブラウザーでそれを行うにはどうすればよいですか?

追加編集

overflowスタイル設定だけではありません。要素にスクロールバーがあるかどうかを確認することは、見かけほど簡単ではありません。上で書いた最初の式は、要素に境界線がない場合は正常に機能しますが、境界線がかなり広い場合(特に境界線の幅offsetが大きい場合)、寸法はscroll寸法より大きくなる場合がありますが、要素はスクロール可能です。offset要素の実際のスクロール可能なビューポートを取得し、それをscroll寸法と比較するには、実際に寸法から境界を差し引く必要があります。

今後の参考のために

:scrollablejQueryセレクターフィルターは私の.scrollintoview()jQueryプラグインに含まれています。誰かがそれを必要とするならば、完全なコードは私のブログ投稿にあります。実際の解決策は提供されていませんが、Soumyaのコードは問題の解決に大きく役立ちました。それは私を正しい方向に向けました。

回答:


118

私はこれを数週間前にどこかで見つけました。それは私のために働いた。

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
あなたは明らかに単純化された例を持っています。コンテナにoverflow:hidden設定されている場合はどうなりますか?余分なコンテンツがありますが、それでもスクロールできません。問題は、見かけほど簡単ではありません。
Robert Koritnik、2011

7
これは受け入れられる解決策ではないかもしれませんが、私にとってはうまくいきました。非表示になっていると、なぜスクロールするのかわかりません。
vol7ron 2011

これは受け入れられる解決策ではないかもしれませんが、私にとってはうまくいきました。Robert、それらのケースでは、CSSオーバーフロープロパティをフェッチして、それらのケースをテストすることもできませんdiv.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden')か(例:)。
vol7ron 2011

7
これは多くの場合失敗します。要素にオーバーフローがある場合:表示されます。幅:200px; また、幅が500pxの子があり、要素にはスクロールバーがありませんが、scrollWidthが500pxでclientWidthが200pxです。
ジョセフレノックス2014年

1
オーバーフローが表示または非表示の場合、通常はスクロールバーはありません。
Hubert Grzeskowiak 16

16

試してください:

垂直スクロールバーの場合

el.scrollHeight> el.clientHeight

水平スクロールバー用

el.scrollWidth> el.clientWidth

これはIE8とFirefox 3.6以降で少なくとも機能することを知っています。


2
これは、特定の要素が見た目よりも大きいことを示していることをイエスに指摘しましたが、それはスクロールバーを表示することを意味するものではありません。それは同様に持つことができ、overflow:hiddenもうスクロールできなくなります。
Robert Koritnik、2011

1
また、clientHeight / clientWidthの値を確認しても、要素にはボーダーが含まれる可能性があるため、このメジャーには含まれていません。私の式を確認してください。それはあなたのものよりよく機能します。
Robert Koritnik、2011

clientHeight / clientWidthの代わりに、offsetHeight / offsetWidthを使用してスクロールバーをチェックする場合も同様です。ご指摘いただきありがとうございます。
ゲイリー

@RobertKoritnik-その特定の要素がoverflow:hiddenそれを持っているかどうかを確認してください...これは最も簡単なので、私の意見では正しい答えです。
vsync 2014年

14

これは見えるかもしれません(またはも)少しハックしていますが、テストすることができscrollTop、およびscrollLeftプロパティを。

それらが0より大きい場合、スクロールバーがあることがわかります。それらが0の場合、それらを1に設定し、もう一度テストして、1の結果が得られるかどうかを確認します。次に、それらを0に戻します。

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

IEには別のプロパティがあると思うので、すぐに更新します。

編集: IEがこのプロパティをサポートしているように見えます。(現在、IEをテストすることはできません。)

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


とを比較するoffsetHeightと、スクロールバーを簡単に確認できますclientHeight。スクロールバーが存在する場合、後者は常にスクロールバーのサイズだけ小さくなります。
Robert Koritnik、2011

@ロバート:簡単かどうかはわかりませんが、どのように機能するかはわかります。次に、要素にがoverflow:scrollある場合は、スクロールバーが有効かどうかに関係なく、その要素がスクロール可能として報告されるようにしたいと思います。もちろん、onscrollイベントがアタッチされている場合、私のソリューションには問題がある可能性があります。
user113716

あんまり。私のjQueryプラグインをチェックすると、実際のスクロール可能な祖先を見つける必要があります。そうしないと、要素をスクロールして表示できません。
Robert Koritnik

8
@RobertKoritnik正しくありません。一部のブラウザには、幅を縮小しないスクロールバーがある場合があります。たとえば、OSX。またはタッチデバイス。
daniel.gindi 2014

1
常にfalseを返す
Fatih Erol

14

ここにさらに別の解決策があります:

少数の人々が指摘したように、offsetHeightとscrollHeightを比較するだけでは十分ではありません。オーバーフローが非表示になっているなど、まだスクロールバーがない要素が異なるためです。だから、ここでも要素の計算されたスタイルでオーバーフローがスクロールか自動かどうかをチェックしています:

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

ある場合overflow*scroll常にスクロールバーがあるのでvertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeight、などが必要だと思います(つまり、角かっこを削除して、scroll*vs client*がの場合にのみテストされるようにしoverflow*ますauto)。それ以外の場合、これが最も正しい解決策のようです。
ジェイク、

@JakeスクロールオーバーフローでscrollHeight <clientHeightの場合、スクロールバーは表示されますが、無効になります(つまり、要素はスクロールできません)。したがって、アプリケーションに依存すると思います。変更は有効であり、スクロールバーを確認したいだけで、状態は関係ありません。私がこれを思いついたとき、コンポーネントに自動スクロールを実装しようとしていたので、その場合はスクロールバーを無効にしても意味がありません。これは、この質問にも当てはまるようです(「人間がスクロールする」必要があります)
lotif

6

パーティーに少し遅れるかもしれませんが...

e.offsetWidth対e.clientWidthでスクロールバーを検出できると思います。オフセット幅には、境界線とスクロールバー、パディングと幅が含まれます。クライアントの幅には、パディングと幅が含まれます。見てください:

https://developer.mozilla.org/en/DOM/element.offsetWidth(2番目の画像) https://developer.mozilla.org/en/DOM/element.clientWidth(2番目の画像)

以下を確認する必要があります。

  1. 要素の計算/カスケード/現在のスタイルを使用して、要素のオーバーフローがauto / scroll(overflowX / Yを含む)に設定されているかどうか。
  2. 要素のオーバーフローがauto / scrollに設定されている場合。offsetWidthとclientWidthを設定します。
  3. clientWidthがoffsetWidth-右側の境界線(compute / cascaded / currentスタイルで再び見つかる)より小さい場合は、スクロールバーがあることがわかります。

バーティカル(offset / clientHeight)についても同じようにします。

IE7は一部の要素についてclientHeightを0と報告します(理由は確認していません)。したがって、常に最初のオーバーフローチェックが必要です。

お役に立てれば!


3

スクロールバーの存在を確認する場合、いくつかの問題があります。その1つは、Macには目に見えるスクロールバーがないため、上記の両方の解決策では正確な答えが得られないことです。

したがって、ブラウザのレンダリングはそれほど頻繁ではないので、スクロールを変更してから設定を元に戻すことができます。

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

(ここまでのところ)上記の解決策のどれもうまくいかなかったので、ここをいじってください。DivのscrollheightとそのoffsetHeightを比較することで、いくつかの成功を見つけました

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

それは私に正確な比較を与えているようです...これまでのところ。これが正当であるかどうか誰かが知っていますか?


2
私はあなたがscrollHeightとclientHeightをしたいと思う:stackoverflow.com/questions/4106538/...
豊富なレーマー

1

以下のためにIE11(Internet Explorerの11)私はにロジックを変更する必要がありました:

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

これは、スクロールバーが存在しない場合、IEがscrollHeightをclientHeightより1大きいと報告し、スクロールバーが存在する場合、約9大きいと報告するためです。


0

Webページ全体にスクロールバーが存在するかどうか、および完全なブラウザーサポートがあるかどうかを知る必要がある場合は、次のように使用できます。

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

それは使用することが重要だwindow.innerHeight代わりのdocument.body.clientHeightため、一部のモバイルブラウザでclientHeightアドレスバーのサイズを取得することはありませんが、scrollHeightは、あなたが間違った計算を取得するので、意志。


-5

この答えはどれも正しくありません。これを使用する必要があります:

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

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

これは、6年前から受け入れられた回答からコピー/貼り付けされており、何かをブール値に変換するために括弧を必要としないため、反対票を投じました。
moto

-6

その中に100%幅の要素を追加します。次に、オーバーフローを非表示に設定します。要素の計算されたスタイル(jQから)が変更された場合、親にはスクロールバーがありました。

編集:getComputedStyleのようなクロスブラウザーメソッドが必要なようです。試してください:

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
これにすでにjQueryを使用している場合は$(el).css("overflow/overflowX/overflowY")、むしろそれを実行して、autoまたはscrollに設定されているかどうかを確認しますしかし、jQueryの使用は避けたいです。
Robert Koritnik、2011

16
CSSスタイルでは、要素スクロールバーがあるかどうかわかりません。スクロールバー持つことができるかどうかのみ。たぶん、内部要素の幅を決定するクロスブラウザ方法を見つけますか?
Soumya

@ Soumya92:スクロール可能なサイズと実際のサイズのサイズ比較は取るに足らないものであり、上記で書きました...ここで確認する必要があるのは、特定の要素の現在のオーバーフロー設定を確認することだけです。
Robert Koritnik、2011

@ Soumya92:それがまさに私が必要としていることです。合体を使用することで、非常に単純化することもできますcomputedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik

もう1つ:クロスブラウザーとはどのようなものですか?これにより、どのブラウザーがサポートされますか?
Robert Koritnik、2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.