1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

スクロールするとヘッダーが自動で隠れるUI作成

Posted at

はじめに

ヘッダーを作成する記事を前回投稿しましたが、それだけでは物足りないですよね。今回はスクロールすることで自動でヘッダーが見え隠れする機能を実装していきたいと思います。

実装のポイント

  1. スクロール方向を検知する
  2. スクロール位置によってヘッダーの表示/非表示を切り替える
  3. CSSを滑らかに動かす

スクロール方向の取得

ReactのuseEffectとuseStateを使用してスクロール量を取得します。

"use client";

import Link from "next/link";
import React, { useEffect, useState } from "react";

const Header = () => {
  const [show, setShow] = useState(true);
  const [lastScrollY, setLastScrollY] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      const currentScrollY = window.scrollY; 
      if (currentScrollY <= 0) {
        setShow(true);
      } else if (currentScrollY > lastScrollY) {
        setShow(false);
      } else {
        setShow(true);
      }
      setLastScrollY(currentScrollY);
    };
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [lastScrollY]);

  return (
    <div
      className={`fixed top-0 left-0 w-full h-16 bg-blue-500 z-10 transition-transform duration-300 flex items-center justify-center text-white text-4xl ${
        show ? "translate-y-0" : "-translate-y-full"
      }`}
    >
      <Link href="/">UI Lab Studio</Link>
    </div>
  );
};

export default Header;

ポイント

  • show
    ヘッダーが見えている状態をtrueで保持、隠れている状態をfaluseで保持
  • lastScrollY
    前回のスクロール位置を保持して、ヘッダーの表示を管理
  • translate-y-0 / -translate-y-full
    TailwindCSSでヘッダーの表示を管理
  • transition-transform duration-300
    スムーズにアニメーションさせるための設定。

useEffect内の説明

少し複雑な設計になっているように見えますが、理解すると簡単なので詳しく解説していきます。

useEffect

Reactの副作用をコンポーネントのレンダリング後に表示するものです。今回は「lastScrollY」が指定されているので、こちらの値が変更されるたびに副作用が働きます。

useEffect(() => { ... }, [lastScrollY]);

スクロールの位置を数値で管理

まず数値を入れる箱「currentScrollY」を作成します。window.scrollYはブラウザの縦スクロール量をピクセル単位で返すプロパティです。

  • 下にスクロールすると → 数字が大きくなる
  • 上にスクロールすると → 数字が小さくなる
 const currentScrollY = window.scrollY; 

表示/非表示の分岐

一つ目のif文で値が0以下なら表示する設定にします。これは最上部0であってもヘッダーが表示されるようにしています。

次にcurrentScrollY > lastScrollY(0)は下にスクロールしたら値が増えるので、下にスクロールしたら画面からヘッダーが消えるようにsetShow(false)になっています。

最後にelseはそれ以外なら表示するように設定しています。操作していないときは表示するように設定します。

if (currentScrollY <= 0) {
        setShow(true);
      } else if (currentScrollY > lastScrollY) {
        setShow(false);
      } else {
        setShow(true);
      }
      setLastScrollY(currentScrollY);
};

windowの監視

ブラウザの window に対してスクロールイベントを監視するよう指示しています。
scrollは縦/横スクロールが発生したときにイベントが発火します。
handleScrollはスクロール時に呼び出される関数ですね。ここに設定することで表示/非表示をを操作するhandleScroll を呼び出せるわけです。

window.addEventListener("scroll", handleScroll);

クリーンアップ関数

ReactのuseEffectで返すクリーンアップ関数。コンポーネントがアンマウント(画面から消える)時に呼ばれます。スクロールイベントの監視を解除しメモリリークを防止します。画面から消えた時に監視をやめる設定と覚えましょう。

return () => window.removeEventListener("scroll", handleScroll);

画面の表示/非表示
こちらでshowがtrueかfalseで表示/非表示の審判を下すことになります。

show ? "translate-y-0" : "-translate-y-full"

なめらかな遷移

transition-transform でアニメーションを追加することができます。
duration-300は遷移までの所要時間になります。今回は300なので0.3秒かけて表示/非表示を行います。

transition-transform duration-300

おわりに

ヘッダーの表示・非表示の仕組みは、アプリを使っているときに一度は目にしたことがあるのではないでしょうか。
PCではあまり便利さを感じないかもしれませんが、スマホでの操作では、画面を広く使えるだけでなく、ユーザー体験(UX)をさりげなく向上させる大切な要素です。
Webアプリやブログサイトを作る際には、ぜひ取り入れてみてください。

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください!
▼▼▼

下記記事ではCSSの紹介ページを運営していますので参考にしていただければと思います。
▼▼▼

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?