スクロールの途中でヘッダーを固定させる方法を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以下に対応する案件自体、減少傾向にあるので気にせず使えそうですね。
ではまた!