🙆
【React】上スクロールした時のみ固定表示するヘッダーを実装する方法
検索機能がついているサイトでよくある、画面を上にスクロールすると検索窓のついたヘッダーが固定表示される機能の実装方法をまとめます。
※例えば、クックパッド(スマホ版)のレシピを表示する画面では画面を下にスクロールしている際は以下の画像のようにヘッダーには何も表示されません。
しかし、上にスクロールすると以下の画像のようにヘッダーに検索窓が固定表示されます。
結論
以下のようなコードになります。
※CSSはTailwind CSSを用いています。
import { useState, useEffect } from "react";
const Header = () => {
const [isSticky, setIsSticky] = useState(false);
const [lastScrollY, setLastScrollY] = useState(0);
useEffect(() => {
const handleScroll = () => {
const currentScrollY = window.scrollY;
if (currentScrollY < lastScrollY) {
setIsSticky(true);
} else {
setIsSticky(false);
}
setLastScrollY(currentScrollY);
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [lastScrollY]);
return (
<header
className={`transition-all ease-in-out duration-300 w-full ${
isSticky
? "fixed top-0 left-0 bg-yellow-200 z-50"
: "relative"
} p-4`}
>
<h1 className={`text-xl ${isSticky ? "text-lg" : "text-2xl"} text-black`}>
上にスクロールした時のみ固定表示
</h1>
</header>
);
};
export default Header;
ポイントは上にスクロールされたことを検知し、上にスクロールされた場合はヘッダーに固定表示するためのスタイルを付与することです。
上にスクロールされたことを検知する方法
コードの以下の部分で検知しています。
useEffect(() => {
const handleScroll = () => {
const currentScrollY = window.scrollY;
if (currentScrollY < lastScrollY) {
setIsSticky(true);
} else {
setIsSticky(false);
}
setLastScrollY(currentScrollY);
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [lastScrollY]);
スクロールされる度に以下のような流れの処理が動きます。
- 直近のスクロール位置が
lastScrollY
に記録されている - 現在のスクロール位置(
currentScrollY
)を取得 - 直近のスクロール位置と現在のスクロール位置を比較
- 現在のスクロール位置の方が上であれば、ヘッダーに固定表示するためのスタイルを付与
上に固定表示させるためのスタイル
Tailwind CSSで書くと以下です。
fixed top-0 left-0 bg-yellow-200 z-50
通常のCSSの形式に直すと以下です。
// 固定する位置を指定(必須)
position: fixed;
top: 0;
left: 0;
// 目立たせるために便宜上背景色を黄色にする(必須ではない)
background-color: rgb(254 240 138);
// 他の要素より上に配置(必須、値は他の要素のz-indexとの兼ね合いで調整する)
z-index: 50;
Discussion