スクロールを制御しよう
要素のサイズや位置の取得方法、スクロールを制御する方法を学びます。
更新:
環境:windows10/Microsoft Edge/VS Code
PREPARATION
想定する読者と前提条件
基本的なパソコン操作ができること。HTML及びJavaScriptの基礎程度の知識が必要です。
START
スクロールバーとは
スクロールとは、表示領域より大きなコンテンツを表示する際にコンテンツを移動(スクロール)しながら全体を閲覧させるためのツールの総称です。 HTMLの場合、ドキュメント全体に対するスクロールバーと特定要素におけるスクロールバーの2種類が存在します。 下記例では上下のみですが、左右に対するスクロールバーも有ります。
スクロールバーの表示条件は?
Webページでスクロールバーが表示されるためには、いくつかの条件があります。 表示領域より表示するコンテンツの大きさが大きいこと。cssのoverflowプロパティがscrollまたはautoに設定されていることです。 また、overflowの設定が有効になるためには、親要素(ブロックレベル要素)に高さ (height または max-height) を設定(縦スクロールの場合)するか、 white-space を nowrap に設定(横スクロールの場合)する必要があります。
overflowプロパティ
overflowの種類
- overflow
-
内包するコンテンツが表示領域より大きい場合の表示方法を決定します。設定値が1つの場合、縦横に対して同じ値を設定することができます。2つの設定値が指定された場合、最初の値は横方向、2つ目の値は縦方向の表示方法を設定できます。
- overflow-x
-
このプロパティは横方向にはみ出した要素の表示方法を決定します。
- overflow-y
-
このプロパティは縦方向にはみ出した要素の表示方法を決定します。
overflowの設定値
- visible
- hidden
-
はみ出した要素は表示されません。ただしプログラムからはスクロール可能です。
- clip
-
はみ出した要素は表示されません。プログラムからもスクロールできません。
- scroll
-
常にスクロールバーを表示してコンテンツを描画します。
吾輩 ( わがはい ) は猫である。
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。 - auto
-
内包する要素によってスクロールバーの表示・非表示を決定します。
吾輩 ( わがはい ) は猫である。
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。 - initial(参考まで)
-
プロパティを初期値に設定します。
- unset(参考まで)
-
継承プロパティは継承値に、それ以外は初期値に設定します。
- inherit(参考まで)
-
要素のプロパティを親と同じ値にします。
overflow TEST
CSSの設定
overflow-x
visible
scroll
auto
overflow-y
visible
scroll
auto
white-space
normal
nowrap
表示のチェック
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で
一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから
別段恐しいとも思わなかった。
要素の大きさを取得しよう
スクロールを制御するためには、要素の大きさを知る必要があります。 ここでは、ドキュメント全体の大きさや特定の要素の大きさを取得する方法を学びましょう。
ビューポートのサイズを取得する
innerWidth/innerHeightを使用し、ブラウザの表示領域の大きさを取得できます。
// 垂直スクロールバー(表示されている場合)を含む、ブラウザウィンドウの ビューポート (viewport) の幅(ピクセル)を返します。
window.innerWidth;
// 水平スクロールバー(表示されている場合)を含む、ブラウザウィンドウの ビューポート (viewport) の高さを返します。
window.innerHeight;
スクロールバーを除く大きさが必要な場合には、以下を使用してください。
document.documentElement.clientWidth/document.documentElement.clientHeight
window.innerWidth | |
---|---|
window.innerHeight | |
document.documentElement.clientWidth | |
document.documentElement.clientHeight |
ドキュメント全体のサイズを取得する
ビューポート外の表示されない部分も含む全体サイズを取得する方法です。取得できる値はブラウザに依存する場合もありますので、注意深く値を観察し使用するものを決定してください。
//画面に表示されない部分を含めた、要素の中身の幅を返します。
document.documentElement.scrollWidth;
document.documentElement.offsetWidth;
document.body.scrollWidth;
document.body.offsetWidth;
document.body.clientWidth;
//画面に表示されない部分を含めた、要素の中身の高さを返します。
document.documentElement.scrollHeight;
document.documentElement.offsetHeight;
document.body.scrollHeight;
document.body.offsetHeight;
document.body.clientHeight;
document.documentElement.scrollWidth | |
---|---|
document.documentElement.offsetWidth | |
document.body.scrollWidth | |
document.body.offsetWidth | |
document.body.clientWidth | |
document.documentElement.scrollHeight | |
document.documentElement.offsetHeight | |
document.body.scrollHeight | |
document.body.offsetHeight | |
document.body.clientHeight |
これらの値は、ブラウザによって異なる場合があります。大きさを取得できる各値を比較し最大値をドキュメントサイズと判断してください。
let scrollWidth = Math.max(
document.body.scrollWidth, document.documentElement.scrollWidth,
document.body.offsetWidth, document.documentElement.offsetWidth,
document.body.clientWidth
);
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight
);
要素のサイズを取得する
特定の要素の大きさを取得してみましょう。パディングやボーダーによっても得られる大きさが異なりますので、確認してみましょう。
//要素の大きさの取得は取得する目的に合わせて使い分けましょう。
Element.scrollWidth;//スクロールする場合、非表示部分を含む全体の幅。(ボーダー・マージン含まず)
Element.offsetWidth;//ボーダー・スクロールバーを含む要素の幅(スクロールの非表示領域は除く)
Element.clientWidth;//ボーダーを除く要素の幅(スクロールの非表示領域は除く)
Element.scrollHeight;//スクロールする場合、非表示部分を含む全体の高さ。(ボーダー・マージン含まず)
Element.offsetHeight;//ボーダー・スクロールバーを含む要素の高さ(スクロールの非表示領域は除く)
Element.clientHeight;//ボーダーを除く要素の高さ(スクロールの非表示領域は除く)
要素のサイズ TEST
CSSの設定
パディング(px)
0
top:10
left:10
all:10
ボーダー(px)
0
top:10
left:10
all:10
幅(px)
200px
auto
高さ(px)
200px
auto
overflow-x
visible
scroll
auto
overflow-y
visible
scroll
auto
white-space
normal
nowrap
表示のチェック
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で
一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから
別段恐しいとも思わなかった。
Element.offsetWidth | |
---|---|
Element.clientWidth | |
Element.scrollWidth | |
Element.offsetHeight | |
Element.clientHeight | |
Element.scrollHeight |
スクロール位置を取得しよう
ドキュメント全体のスクロール位置やスクロールバーが表示されている特定の要素内のスクロール位置を取得する方法を学びましょう。
ドキュメント全体のスクロール位置
スクロールバーが表示されている場合に、画面の左上からの移動距離をpageXOffset/pageYOffsetを用いることで
スクロール位置を取得することができます。
※pageXOffset プロパティは、scrollX プロパティのエイリアスです。
※pageYOffset プロパティは、scrollY プロパティのエイリアスです。
クロスブラウザー互換性のためpageXOffset/pageYOffsetを利用しています。
// 左端からのスクロール位置を返します。
window.pageXOffset;
// 上端からのスクロール位置を返します。
window.pageYOffset;
window.pageXOffset | |
---|---|
window.pageYOffset |
特定の要素内のスクロール位置
スクロールバーが表示されている場合に、要素の左上からの移動距離をscrollTop/scrollLeftを用いることで スクロール位置を取得することができます。
// 左端からのスクロール位置を返します。
Element.scrollLeft ;
// 上端からのスクロール位置を返します。
Element.scrollTop ;
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で
一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから
別段恐しいとも思わなかった。
Element.scrollLeft | |
---|---|
Element.scrollTop |
要素の位置を取得しよう
特定の要素の位置を取得するためには、Element.getBoundingClientRect()を用いることで、ビューポート(表示画面)からの位置を取得することができます。 返り値よりleft, top, right, bottom等が取得でき、要素の位置を計算できます。
//特定の要素の位置を取得する
let domRect = element.getBoundingClientRect();
domRect.left;//表示領域から見た画面左端からの位置。
domRect.top;//表示領域から見た画面上端からの位置。
domRect.right;//表示領域から見た画面左端からの位置+要素幅の位置。
domRect.bottom;//表示領域から見た画面上端からの位置+要素の高さの位置。
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で
一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから
別段恐しいとも思わなかった。
left | |
---|---|
top | |
right | |
bottom | |
width | |
height |
スクロールを制御しよう
さて、要素のサイズの取得方法やスクロール位置の取得方法を学びました。今度はこれらを活用し、スクロールを制御する方法を学びましょう。 ここでは、基本的なスクロール方法であるscrollTo, scrollBy, scrollIntoViewの3つを取り上げます。
scrollTo
window.scrollTo(x,y)は、文書の左上(0,0)を起点とした移動量で文書をスクロールすることができます。 window.scrollTo(option)と指定することもでき、この場合、left、top、behavior(smooth、 instant、 auto)の3つのオプションが指定できます。
しかしこのオプションを使った指定方法は、対応するブラウザが限定されるためここでは紹介だけにします。
//使用例
window.scrollTo(0, 0);//画面を最上部に移動する。
scrollTo(0, 0);//scrollToだけでも動作します。
//optionを用いた指定方法
window.scrollTo({
top: 0,
left: 0,
behavior: "smooth"
});
scrollBy
window.scrollBy(x,y)は、現在表示されている表示領域の左上(0,0)を起点とした移動量で文書をスクロールすることができます。
//使用例
window.scrollBy(0, window.innerHeight);//1ページ分下にスクロールする。
scrollBy(0,window.innerHeight);//scrollByだけでも動作します。
scrollIntoView
Element.scrollIntoView(Boolean)は、呼び出された要素がユーザーに見えるところまで、スクロールします。 Element.scrollIntoView(option)と指定することもでき、この場合、behavior(auto,smooth)、block(垂直方向:start, center, end, nearest。既定値はstart)、inline(水平方向:start, center, end, nearest。既定値はnearest)の3つのオプションが指定できます。
完全に対応するブラウザが限られるため紹介のみとなります。動作は以下のページを御覧ください。
//使用例
Element.scrollIntoView();//trueと同じ動作
Element.scrollIntoView(true); // {block: "start", inline: "nearest"} と同じ。
Element.scrollIntoView(false); // {block: "end", inline: "nearest"} と同じ。
Element.scrollIntoView({behavior:"auto", block:"start", inline:"nearest"}); // オブジェクト型の引数
scrollLeft/scrollTop
特定の要素内のスクロールを制御するためには、scrollLeft/scrollTopにスクロールするピクセル数を設定します。基準は要素の左上(0,0)が起点となります。
//使用例
Element.scrollLeft = 0;
Element.scrollLeft = 100;
Element.scrollTop = 0;
Element.scrollTop = 200;
よくある課題解決のために
スクロールに関する短いコードサンプルをいくつかご紹介します。
画面最上部に移動するには
//0,0とすることで、画面左上に移動します。アニメーション無し。
scrollTo(0,0);
scrollToのオプション機能を活用し、スムーズに画面左上に移動。
//しかし対応ブラウザが非常に少なく、使えるようになるにはもう少しかかります。
scrollTo({top: 0, left: 0, behavior: "smooth"});
画面最下部に移動するには
//htmlの高さ- スクロールバーを除くビューポートの高さとすることで、
//画面下部に移動します。アニメーション無し。
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight
);
scrollTo(0, scrollHeight - document.documentElement.clientHeight);
//htmlの高さを渡すだけでも動作します。
scrollTo(0, scrollHeight);
//scrollToのオプション機能を活用し、スムーズに画面下部に移動。
//しかし対応ブラウザが非常に少なく、使えるようになるにはもう少しかかります。
scrollTo({top: scrollHeight, left: 0, behavior: "smooth"});
画面右端に移動するには
//htmlの幅 - スクロールバーを除くビューポートの幅とすることで、
画面右端に移動します。アニメーション無し。
let scrollWidth = Math.max(
document.body.scrollWidth, document.documentElement.scrollWidth,
document.body.offsetWidth, document.documentElement.offsetWidth,
document.body.clientWidth
);
scrollTo(scrollWidth - document.documentElement.clientWidth, 0);
//そのままhtmlの幅を渡すだけでも動作します。
scrollTo(scrollWidth, 0);
//scrollToのオプション機能を活用し、スムーズに画面右端に移動。
//しかし対応ブラウザが非常に少なく、使えるようになるにはもう少しかかります。
scrollTo({top: 0, left: scrollWidth, behavior: "smooth"});
画面最上部判定
//window.pageYOffsetが0の場合画面の最上部にいるかどうか判定できます。
if( window.pageYOffset === 0 ){
//画面最上部
}
//比較対象数字を少し増やすことで、最上部付近を表現
if( window.pageYOffset < 200 ){
//画面最上部付近
}
//ビューポートの高さと比較しても良い。
if( window.pageYOffset < document.documentElement.clientHeight ){
//画面最上部付近
}
画面最下部判定
//window.pageYOffsetの値と判定することで最下部にいるかどうか判定します。
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight
);
let bottom = scrollHeight - document.documentElement.clientHeight;
if( window.pageYOffset >= bottom ){
//画面最下部
}
//bottomを少し減らすことで最下部付近を表現できます。
if( window.pageYOffset >= (bottom - 200) ){
//画面最下部付近
}
スクロールバー表示判定
//X軸スクロールバー判定
if( window.innerWidth >= document.documentElement.clientWidth ){
//スクロールバー無し
}
//Y軸スクロールバー判定
if( window.innerHeight >= document.documentElement.clientHeight ){
//スクロールバー無し
}
//特定の要素の場合(overflow:auto限定)
//overflowの値がhiddenの場合は常に非表示。
//overflowの値がscrollの場合は常に表示。
let element = document.querySelector("");
if(element.scrollWidth > element.clientWidth ){
//スクロールバー有り
}
if(element.scrollHeight > element.clientHeight ){
//スクロールバー有り
}
要素の画面上での位置
let element = document.querySelector("");
let domRect = element.getBoundingClientRect();
//X軸の位置(要素の左上基準)
window.pageXOffset + domRect.left;
//Y軸の位置(要素の左上基準)
window.pageYOffset + domRect.top;
スクロール要素内での位置
let scrollParentElement = document.querySelector("");
let childElement = document.querySelector("");
//X軸の位置(要素の左上基準)
let xpos = childElement.getBoundingClientRect().left - scrollParentElement.getBoundingClientRect().left + scrollParentElement.scrollLeft;
//Y軸の位置(要素の左上基準)
let ypos = childElement.getBoundingClientRect().top - scrollParentElement.getBoundingClientRect().top + + scrollParentElement.scrollTop;
//見えるようにスクロール(X軸)
scrollParentElement.scrollLeft = xpos;
//見えるようにスクロール(Y軸)
scrollParentElement.scrollTop = ypos;
//scrollIntoViewを使った例。計算不要。
childElement.scrollIntoView();