ウィンドウを下へスクロールすると隠れ、上にスクロールすると表示されるヘッダーの作り方です。下へスクロールすると隠れる仕様の場合、ウィンドウがページの最下部に到達したときもヘッダーが隠れたままになるため、最後までページ内のコンテンツを見終えた時点で再度ヘッダーを表示させるようにします。
※ CSSは動作に必要な部分のみを記述しています。
※ CSSのベンダープレフィックスは最新2バージョンを対象としています。
実現したいこと
- スクロールするとヘッダーが画面上部に固定される
- 下へスクロールするとヘッダーが隠れる
- 上へスクロールするとヘッダーが表示される
- 画面最下部に到達したらヘッダーを表示する
ヘッダーを画面上部に固定する
htmlにヘッダーを作成します。
<header id="header" class="header">
<h1>Header</h1>
</header>
CSSのposition: fixed
で画面上部に固定します。
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
ヘッダー表示・非表示の設定(CSS)
ヘッダーの表示・非表示はclass名の追加・削除で行います。非表示にする場合はtransform: translateY(数値);
でヘッダーを画面外に移動し、表示する場合は transform: trasnlateY(0)
で画面の最上部の位置に戻します。
.header {
-webkit-transform: translateY(0);
transform: translateY(0);
}
.header--unpinned {
-webkit-transform: translateY(-150%);
transform: translateY(-150%);
}
動きにアニメーションを付ける場合は header
に transition
プロパティで指定します。
.header {
-webkit-transition: -webkit-transform 0.4s ease;
transition: -webkit-transform 0.4s ease;
transition: transform 0.4s ease;
transition:
transform 0.4s ease,
-webkit-transform 0.4s ease;
}
JavaScriptでウィンドウをスクロールしたら実行する関数を作成
ウィンドウがスクロールされたときに何かを実行したい場合は window.addEventListener
メソッドを scroll
を対象にして設定し、実行したい関数を指定します。
const onScroll = () => {
console.log("scroll");
};
window.addEventListener("scroll", () => {
onScroll();
});
上下どちらにスクロールした場合も、コンソールに「scroll」と表示されます。
スクロール時に実行する関数を作成
指定量スクロールしたらヘッダーを隠すようにします。どのくらいスクロールしたかどうかは window.scrollY
で取得します。ここではheaderの高さ分より多くスクロールした場合にヘッダーが隠れるようにしたいので、 スクロール量 > ヘッダーの高さ
の場合にclass名を追加します。
// ヘッダーを取得
const header = document.getElementById("header");
// ヘッダーの高さを取得
const hH = header.clientHeight;
// 現在地を示す変数を定義
let pos = 0;
const onScroll = () => {
// スクロール位置がヘッダーの高さ分より大きい場合にclass名を追加し、そうでない場合にclass名を削除
if (pos > hH) {
header.classList.add("header--unpinned");
} else {
header.classList.remove("header--unpinned");
}
};
window.addEventListener("scroll", () => {
// スクロールするごとにpos(現在地)の値を更新
pos = window.scrollY;
onScroll();
});
ヘッダーの高さあたりをスクロールすると、classが付いたり取れたりします。
上へスクロールした場合に再びヘッダーが表示されるようにするには、現在地 < 最後(直前)のスクロール位置
の場合にclass名の追加を行います。最後のスクロール位置の値の保存は、onScroll();
関数内で行います。
ここで先ほど if/else
で記述した部分を変更します。 class名の追加は「スクロール位置がヘッダーの高さ分より大きく且つ最後のスクロール位置より大きい」場合に行うので問題ありませんが、class名の削除をelseで行おうとすると「スクロール位置がヘッダーの高さ分より小さい」ことも必須条件になるため、class名の削除を行う条件を別のif文として記述します。
// スクロール直前の位置を示す変数を定義
let lastPos = 0;
const onScroll = () => {
if (pos > hH && pos > lastPos) {
header.classList.add("header--unpinned");
}
// スクロール位置がヘッダーの高さ分より小さいか
// またはスクロール位置が最後のスクロール位置より小さい場合はclass名を削除
if (pos < hH || pos < lastPos) {
header.classList.remove("header--unpinned");
}
// 最後のスクロール位置を保存
lastPos = pos;
};
ヘッダーの高さ分より下の範囲ではどの位置でも、下へスクロールするとヘッダーが隠れ、上へスクロールするとヘッダーが表示されるようになりました。
ページの最下部に到達したらヘッダーを表示する
ページ最下部に到達したかどうかを調べるには、ページ全体の高さからウィンドウの高さを引くとウィンドウが最下部に達した場合のウィンドウ上部の位置が得られます。スクロール量(window.scrollY
)がこの位置に到達したらヘッダーを表示するようにします。
// ウィンドウの高さを取得
const winH = window.innerHeight;
// ページの高さを取得
const docH = document.documentElement.scrollHeight;
// ウィンドウが最下部達した場合のウィンドウ上部の位置を取得
const windBtm = docH - winH;
class名の削除を行うif文の条件に、スクロール量がウィンドウ下部に達した場合 windBtm <= pos
を追記します。
if (pos < hH || pos < lastPos || windBtm <= pos) {
header.classList.remove("header--unpinned");
}
スクロールがページの最下部まで到達した際に、ヘッダーが再び表示されるようになりました。
デモ
下へスクロールすると隠れて、上にスクロールすると表示されるヘッダー
Source
参考サイト
Akira「下スクロールで消える・上スクロールで現れる素の JavaScript」(参照2019-11-15)