ブラウザウィンドウの幅を知るためには?スクロールアウトされた部分を含め、ドキュメントの高さを取得するには?JavaScript を使用してページをスクロールするにはどうすればよいでしょうか?
DOM の観点からは、ルートドキュメント要素は document.documentElement
です。その要素は <html>
に対応し、前のチャプター で説明したジオメトリプロパティを持っています。場合によってはそれを使うことができますが、考慮すべき重要な追加の方法や特性があります。
ウィンドウの幅/高さ
document.documentElement
のプロパティ clientWidth/clientHeight
はまさに私たちがここで欲しいものです:
例えば、このボタンはあなたのウィンドウの高さを表示します。:
window.innerWidth/Height
ではありませんブラウザはプロパティ window.innerWidth/innerHeight
もサポートしています。
それらは私たちがほしいものに見えます。何が違うのでしょう?
もし、スペースを占めるスクロールバーがある場合、clientWidth/clientHeight
はその中の 幅/高さ を提供します。言い換えれば、ドキュメントの可視部分の幅/高さ、コンテンツで利用可能な値を返します。
そして、window.innerWidth/innerHeight
はスクロールバーを無視します。
もしスクロールバーがあり、それがあるスペースを占める場合、これら2つの行は異なる値を表示します:
alert( window.innerWidth ); // ウィンドウ幅
alert( document.documentElement.clientWidth ); // ウィンドウ幅 - スクロールバー
ほとんどの場合、利用可能な ウィンドウ幅が必要です: 何かを描画または配置するために。つまり: スクロールバーがある場合にはその内側です。したがって、documentElement.clientHeight/Width
を使うべきです。
DOCTYPE
は重要です注意: HTML の中に <!DOCTYPE HTML>
がないとき、トップレベルのジオメトリプロパティは少し異なって動作する可能性があります。奇妙なことが起こり得ます。
現代の HTML では、常に DOCTYPE
を書くべきです。一般的にそれは JavaScript の問題ではありませんが、ここでは JavaScript へも影響します。
ドキュメントの幅/高さ
理論上は、ルートドキュメント要素は documentElement.clientWidth/Height
であり、すべてのコンテンツを囲むので、フルサイズを documentElement.scrollWidth/scrollHeight
で測定できます。
これらのプロパティは通常の要素に対しては上手く動作します。しかしページ全体の場合、これらのプロパティは意図したとおりには動作しません。Chrome/Safari/Opera では、スクロールが無い場合、documentElement.scrollHeight
は documentElement.clientHeight
よりも小さいかもしれません! 通常の要素の場合、それはナンセンスです。
信頼できるウィンドウサイズを取得するために、それらのプロパティの最大を取る必要があります。:
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
alert('Full document height, with scrolled out part: ' + scrollHeight);
なぜそうなのでしょう?が、聞かない方が良いです。これらの不一致は古くからのものであり、 “スマート” なロジックではありません。
現在のスクロールを取得する
通常の要素は elem.scrollLeft/scrollTop
に現在のスクロール状態を持っています。
ページではどうでしょう?ほとんどのブラウザはドキュメントのスクロールのための documentElement.scrollLeft/Top
を提供していますが、Chrome/Safari/Opera はバグ (157855, 106133 のような) があり、document.documentElement
の代わりに document.body
を使用してください。
幸いにも、特別なプロパティ window.pageXOffset/pageYOffset
により、これらの特殊性を覚える必要は全くありません。:
alert('Current scroll from the top: ' + window.pageYOffset);
alert('Current scroll from the left: ' + window.pageXOffset);
これらのプロパティは読み取り専用です。
スクローリング: scrollTo, scrollBy, scrollIntoView
JavaScript からページをスクロールするには、その DOM を完全に構築する必要があります。
例えば、<head>
でスクリプトからページをスクロールしようとした場合、それは動作しません。
通常の要素は scrollTop/scrollLeft
を変更することでスクロールすることが出来ます。
ページに対して同じことができます:
- Chrome/Safari/Opera を除くすべてのブラウザ:
document.documentElement.scrollTop/Left
を変更します。 - Chrome/Safari/Opera の場合: 代わりに
document.body.scrollTop/Left
を使います。
それは動作しますが、クロスブラウザの非互換の匂いがします。良いことではありません。幸運なことに、よりシンプルでユニバーサルな解決策があります: 特別なメソッド window.scrollBy(x,y) と window.scrollTo(pageX,pageY) です。
-
メソッド
scrollBy(x,y)
は現在の位置を基準としてページをスクロールします。例えば、scrollBy(0, 10)
はページを下に10px
スクロールします。下のボタンはこのデモをします:
-
メソッド
scrollTo(pageX,pageY)
はドキュメントの左上の角を基準としてページをスクロールします。これはscrollLeft/scrollTop
の設定に似ています。一番先頭にスクロールするには、
scrollTo(0,0)
を使います。
これらのメソッドは同じ方法ですべてのブラウザで動作します。
scrollIntoView
完全性のために、もう1つメソッドを説明しましょう: elem.scrollIntoView(top).
elem.scrollIntoView(top)
への呼び出しは elem
が見えるようにページをスクロールします。1つの引数を持っています。:
- もし
top=true
(デフォルト) の場合、elem
がウィンドウの上部に表示されるようページがスクロールされます。要素の上端はウィンドウの上部に揃います。 - もし
top=false
の場合、elem
が下部に表示されるようページがスクロールされます。要素の下端はウィンドウの下部に揃います。
下のボタンは自身をウィンドウの上部に表示するようページをスクロールします:
そして、このボタンは下部に表示するようページをスクロールします。:
スクロールを禁止する
私たちはドキュメントを “スクロール不可” にする必要がある場合があります。例えば、すぐに注意を必要とするようなサイズの大きなメッセージを伝える必要があるとき、訪問者にはドキュメントではなく、そのメッセージとやりとりすることを望みます。
ドキュメントをスクロール不可にするためには、document.body.style.overflow = "hidden"
を設定すれば十分です。ページは現在のスクロールで止まります。
やってみましょう:
1つ目のボタンはスクロールをフリーズさ、2つ目は再開します。
私たちは、document.body
だけでなく他の要素に対しても、スクロールを “フリーズ” させる同じテクニックが使えます。
このメソッドの欠点は、スクロールバーが消えることです。もしスクロールバーがスペースを占めていたら、そのスペースは今や解放されているので、コンテンツはそれを埋めるために “ジャンプ” します。
それは少し変に見えますが、フリーズする前後で clientWidth
を比較し、スペースが増えた場合(スクロールバーが消えたら)、コンテンツ幅を同じに維持するためにスクロールバーの代わりに document.body
に padding
を追加することで回避できます。
サマリ
ジオメトリ:
-
ドキュメントの可視部分の幅/高さ(コンテンツ領域の幅/高さ):
document.documentElement.clientWidth/Height
-
スクロールアウト部分も含むドキュメント全体の幅/高さ:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
スクローリング:
-
現在のスクロールを読む:
window.pageYOffset/pageXOffset
. -
現在のスクロールを変更する:
window.scrollTo(pageX,pageY)
– 絶対座標,window.scrollBy(x,y)
– 現在の場所を基準にスクロール,elem.scrollIntoView(top)
–elem
が見えるようにスクロール (ウィンドウの上部/下部に揃う).
コメント
<code>
タグを使ってください。複数行の場合は<pre>
を、10行を超える場合にはサンドボックスを使ってください(plnkr, JSBin, codepen…)。