目次

スクロールを制御しよう

要素のサイズや位置の取得方法、スクロールを制御する方法を学びます。


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

hidden

scroll

auto

overflow-y

visible

hidden

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

hidden

scroll

auto

overflow-y

visible

hidden

scroll

auto

white-space

normal

nowrap

表示のチェック

吾輩 ( わがはい ) は猫である。
名前はまだ無い。
どこで生れたかとんと 見当がつかぬ。
何でも薄暗いじめじめした所で
ニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で
一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから
別段恐しいとも思わなかった。
top:/
bottom:/
scrollX:/
scrollY:
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つのオプションが指定できます。

完全に対応するブラウザが限られるため紹介のみとなります。動作は以下のページを御覧ください。

scrollIntoView Demo

//使用例
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();


COMPLETE


  • avatar
    お疲れ様でした!

    今回はスクロールについて詳しく見てきました。 要素のサイズを取得する方法、要素の位置を取得する方法をしっかり抑えておけば、様々な状況に対応できますね。


コメント