スクロールの途中でヘッダーを固定させる方法を2つ紹介します。
JavaScriptとCSSで実装する方法と、CSSのみで実装する方法があります。
共通HTML
HTMLは共通です。pタグ内のテキスト部分は長いので省略しています。
<div class="container">
<div class="hero">
Scroll Down
</div>
<header class="header">
Header
</header>
<main class="main">
<p>略...</p>
</div>
</div>JavaScriptとCSSで実装する方法
サンプル
スクロール位置がヘッダーに差し掛かると、ヘッダーに対して.fixedというクラスをJavaScriptで追加しています。
See the Pen Scroll Header (JS & CSS) by POSIPAN (@posipan) on CodePen.
CSS
ポイントとなる部分を抜粋しています。
.fixedのposition: fixed;により、ヘッダーが固定されます。
また、.fixedが追加されると、main要素に対してpadding-top(ヘッダーの高さ + mainのpadding-topの値)を設定しています。
これはヘッダーが固定モードになる際のカクツキを防ぐためです。
試しにpadding-topを削除してみると良いでしょう。
header {
background: #bbb;
width: 100%;
height: 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
// .fixedを追加した時のCSS
&.fixed {
position: fixed;
top: 0;
+ main {
padding-top: 75px;
}
}
}
.main {
padding: 15px;
max-width: 600px;
margin: 0 auto;
line-height: 2;
}JavaScript
変数fixedにページの最上部からヘッダーまでの座標位置(px)を格納しています。
fixHeader関数の中で、スクロールによって変化するwindow.pageYOffsetの値と変数fixedの値を比較しています。
その結果によって、headerに対してクラス.fixedの追加・削除を行なっています。
window.addEventListener('scroll', fixHeader);
const header = document.querySelector('.header');
// ヘッダーの座標位置
let fixed = header.getBoundingClientRect().top + window.pageYOffset;
function fixHeader() {
// スクロール量がヘッダーの座標位置を超えた時に.fixedを追加
if (window.pageYOffset > fixed) {
header.classList.add('fixed');
} else {
header.classList.remove('fixed');
}
}Element.getBoundingClientRect()
ブラウザ表示領域の左上(0, 0)からElementまでの相対座標位置を取得するメソッドです。
このメソッドは下記のようなプロパティを持っています。
top– 要素の上端のY座標left– 要素の左端のX座標right– 要素の右端のX座標bottom– 要素の下端のY座標
本サンプルではtopプロパティを使用して、Element.getBoundingClientRect().topでブラウザ表示領域上端からヘッダー上端までのY座標を取得しています。

window.pageYOffsetとは?
pageYOffsetはwindowのプロパティであり、垂直方向のスクロール量を取得できます。
また、本サンプルでは下記のようにElement.getBoundingClientRect().topと組み合わせることでElementの絶体座標を取得することができます。
絶体座標とはページ(ドキュメント)の左上からElementまでの座標位置のことです。
let fixed = header.getBoundingClientRect().top + window.pageYOffset;CSSのみで実装する方法
サンプル
position: sticky;でヘッダーを固定しています。
See the Pen Scroll Header (CSS Only) by POSIPAN (@posipan) on CodePen.
CSS
ポイントとなる部分を抜粋しています。
先程のJS&CSS実装版との違いは、&.fixed〜の箇所を削除し、position: sticky;とtop: 0;を追加している点です。
position: sticky;を指定した要素は要素分の高さを保持しつつ、ブラウザ領域の上端に差し掛かったところで要素が固定されます。
header {
background: #bbb;
width: 100%;
height: 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
// 下記を追加
position: sticky;
top: 0;
}position: sticky;とは?
簡単に言うと、positionのrelative、absolute、fixedの機能を合わせ持つ値です。
今回のようにスクロール途中から要素を固定させることができます。
とてもわかりやすい記事がありましたので、こちらを参考にすると理解が深まります。
https://www.asobou.co.jp/blog/web/css-sticky
おわりに
CSSのみで実装する方が圧倒的に楽でしたね!
position: sticky;はIE11以下では非対応ですが、
IE11以下に対応する案件自体、減少傾向にあるので気にせず使えそうですね。
ではまた!
