#概要
ウィンドウのスクロール量に応じて、表示・非表示を切り替えたり、マイクロインタラクションを入れたり、、などの実装をすることがよくありますが、scrollTop()
やoffset().top
などが、毎回ごっちゃになるので、jQuery/JavaScriptでの各パラメータの取得方法をまとめました。
#基本的な考え方
##各パラメータの取得
ある要素が、スクロールによって、表示領域に入り、その後、表示領域から見えなくなるまでの動きを考えます。
図で表すと下記のようなイメージになります。
図で示したパラメータの取得方法をざっくりまとめると下記のようになります。
|パラメータ| 内容 | jQueryで取得 |JavaScriptで取得 |
|:-:|:-:|:-:|:-:|:-:|
| A | ウィンドウのスクロール量 (ページの上端からの距離) |$(window).scrollTop()| window.pageYOffset |
| B | 表示領域の高さ |$(window).height()|document.documentElement.clientHeight|
| C | 要素の位置 (ページの上端からの距離)| $(elm).offset().top|elm.getBoundingClientRect().top|
| D | 要素の高さ| $(elm).outerHeight()|elm.getBoundingClientRect().height|
##表示条件の考え方
取得したパラメータを組み合わせ、条件式を組み立てます。
- ある要素が表示領域に見え出したら: A + B > C
- ある要素が表示領域に完全に表示されたら: A + B > C + D
- ある要素が表示領域から見えなくなったら: A > C + D
#jQueryを使用する場合
##各パラメータの取得
A. ウィンドウのスクロール量の取得
let scrollPos = $(window).scrollTop();
ページの上端を基準とし、表示領域のスクロール位置(Y座標)をpx値で返します。
B. 表示領域の高さの取得
let winH = $(window).height();
メニューバーなどを含まない、表示領域の高さをpx値で返します。
C. 要素の位置の取得
let elmOffset = $('#box').offset().top;
offset()
は、ある要素が配置されている位置を取得するメソッドです。
offset().top
で、ページの上端を基準とし、要素の上端の位置(Y座標)をpx値で返します。
D. 要素の高さの取得
let elmH = $('#box').outerHeight();
outerHeight()
で要素の高さをpx値で返します。これは、paddingやborderを含む外側の高さです。
optionで、outHeight(true)
とすると、さらにmargin値を含む高さになります。
似たメソッドでinnerHeight()
がありますが、これは、padding/borderを含まない内側の高さを返します。
##実装例
例として、スクロールによって、ある要素(#box3)が表示されると、追従ボタン(#sticky)を非表示になるようなサンプルを作成しました。
$(function() {
let scrollPos; //スクロール量
let elmOffset; //要素(#box3)の位置
let winH = $(window).height(); //表示領域の高さ
$(window).scroll(function() {
scrollPos = $(window).scrollTop();
elmOffset = $('#box3').offset().top;
if (scrollPos + winH > elmOffset) {
$('#sticky').removeClass('is-active');
} else {
$('#sticky').addClass('is-active');
}
});
$(window).resize(function() {
winH = $(window).height();
});
})
<div id="sticky is-active" class="sticky"></div>
<div class="container">
<div id="box1" class="box"><p>コンテンツ1</p></div>
<div id="box2" class="box"><p>コンテンツ2</p></div>
<div id="box3" class="box"><p>コンテンツ3</p></div>
</div>
.container {
width: 1100px;
margin: 50px auto;
}
.container .box {
height: 800px;
}
.sticky {
position: fixed;
bottom: -100px;
left: 0;
width: 100%;
background: #ccc;
height: 50px;
transition: all 0.6s ease-in-out;
z-index: 1;
}
.sticky.is-active {
bottom: 0;
}
#JavaScriptのみで実装する場合
##各パラメータの取得
A. ウィンドウのスクロール量の取得
let scrollPos = window.scrollY; //IE非対応
let scrollPos2 = window.pageYOffset;
let scrollPos3 = document.documentElement.scrollTop;
いずれも、ページの上端を基準とし、表示領域のスクロール位置(Y座標)をpx値で返します。
scrollY: https://developer.mozilla.org/ja/docs/Web/API/Window/scrollY
pageYOffset: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageYOffset
scrollTop: https://developer.mozilla.org/ja/docs/Web/API/Element/scrollTop
B. 表示領域の高さの取得
let winH = document.documentElement.clientHeight;
メニューバーなどを含まない、表示エリアの高さをpx値で返します。
似たプロパティに、window.innerHeight
がありますが、こちらは、水平スクロールバーの高さを含みます。また、window.outerHeight
の場合は、ブラウザ のメニューバーなどを含む外側の高さを返します。
clientHeight: https://developer.mozilla.org/ja/docs/Web/API/Element/clientHeight
innerHeight: https://developer.mozilla.org/ja/docs/Web/API/Window/innerHeight
outerHeight: https://developer.mozilla.org/ja/docs/Web/API/Window/outerHeight
C. 要素の位置の取得
let elm = document.getElementById('box');
let elmOffset = elm.offsetTop;
let elmOffset2 = elm.getBoundingClientRect().top;
いずれもページの上端を基準とし、要素の上端の位置(Y座標)をpx値で返します。
offsetTop: https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/offsetTop
getBoundingClientRect: https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect
D. 要素の高さの取得
let elmH = elm.offsetHeight;
let elmH2 = elm.getBoundingClientRect().height;
let elmH3 = elm.clientHeight; //border含まない
offsetHeight
、getBoundingClientRect().height
は、Padding, borderを含む、要素の高さをpx値で返します。clientHeight
の場合は、Paddingは含まれますが、borderは含まれません。
offsetHeight: https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/offsetHeight
getBoundingClientRect: https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect
clientHeight: https://developer.mozilla.org/ja/docs/Web/API/Element/clientHeight
##実装例
先ほどのjQueryでの実装例をJavaScriptで置き換えたサンプルです。
document.addEventListener('DOMContentLoaded', function() {
let elm = document.getElementById('box3');
let elmSticky = document.getElementById('sticky');
let scrollPos;
let elmOffset;
let winH = document.documentElement.clientHeight;
window.addEventListener('scroll', function() {
scrollPos = window.pageYOffset;
elmOffset = getBoundingClientRect().top;
if (scrollPos + winH > elmOffset) {
elmSticky.classList.remove('is-active');
} else {
elmSticky.classList.add('is-active');
}
})
window.addEventListener('resize', function() {
winH = document.documentElement.clientHeight;
})
})