🏋️

Next.js/Reactでスクロールすると現れるHeaderを実装する

2021/10/11に公開

はじめに

世の中にはおしゃれなLPやHPいろいろなサイトがありますよね。
そういったサイトを見ていくうちにスクロールでHeaderが消えたり現れたりするものがあり気になり自分が制作中の潤羽るしあファンサイトに取り入れたいなと思い学習した事を書いていきます。

現在潤羽るしあファンサイトに完成例がありますので実際の挙動はこちらを見ていただければわかると思います。

※ 潤羽るしあとは自分が推しているホロライブ所属のバーチャルユーチューバーのことです。

注意書き

この記事では以下のことについては扱いません。

今回はTailwind、CSS Module(scss)を用いて実装しています。
他のUIフレームワーク等を使っている場合は逐次置き換えて閲覧お願いします。

スクロールすると現れるheaderを実装する

今回は特に別途追加するものはありません。
基本的にNext.js、Tailwind、cssを用いて実装していきます。

まず仕様をまとめておきます。

  • スクロールすると現れる
  • 現れたら追従する(いわゆるsticky header)

900~1000 <= window.scrollYほどあればフルスクリーン分では表示されないよね?くらいな雑な考えですがご了承ください。

headerの表示非表示を実装

ヘッダーには表示非表示するためのpropsを持たせます。

header.tsx
import styles from './header.module.scss';

type headerProps = {
  isActive: boolean;
};

const Header: VFC<headerProps> = (props) => {
  const style = props.isActive ? styles.active : styles.notActive;

  return (
    <header className={style}>
  ~

表示非表示はCSS側で当てるスタイルを用意します。

header.module.scss
.notActive {
    opacity: 0;
}

.active {
    opacity: 1;
}

これで表示非表示させる準備は整いました。

スクロール制御を行うカスタムフックを作成

表示開始する値を受け取り表示非表示状態をbooleanで返却するようにする。

./src/hooks/useHeaderScroll.ts
import { useEffect, useState } from 'react';

// スクロールを制御する
/**
 * @param {number}  activePoint - 表示のポイントを数値で取得
 * @return {boolean} 表示、非表示のbool値を返却する
 */
const useHeaderScroll = (activePoint: number): boolean => {
  const [isHeaderActive, setIsHeaderActive] = useState<boolean>(false);

  useEffect(() => {
    const scrollWindow = () => {
      const ap = activePoint;
      let scroll = 0;
      scroll = window.scrollY;
      if (ap <= scroll) {
        setIsHeaderActive(true);
      } else {
        setIsHeaderActive(false);
      }
    };
    window.addEventListener('scroll', scrollWindow);
    return () => {
      window.removeEventListener('scroll', scrollWindow);
    };
  }, [activePoint]);

  return { isHeaderActive };
};

export default useHeaderScroll;

表示するコンポーネント設定

headerを表示するコンポーネントの設定を行います。

./src/pages/index.tsx
import Header from '@/components/Header';
+ import useHeaderScroll from '@/hooks/useHeaderScroll';

const Home: NextPage = () => {
  // 900~1000に表示開始する値を設定する
+ const { isHeaderActive } = useHeaderScroll(900);
  return (
    <Layout>
      {/* stickyにする、コンポーネントのレイヤーを+50にする */}
+     <div className="sticky top-0 z-50">
        {/* stickyにすることでheaderのレイアウトが崩れるかもしれないので調整 */}
+       <div className="flex flex-col w-screen">
+         <Header isActive={isHeaderActive} />
+        </div>
+     </div>
      ~
    </Layout>
  );
};

export default Home;

これで完了です。

devで動かしてみましょう。

$ yarn dev

このように表示されれば完成です!
おつかれさまでした!

おわりに

長くなってしまいしたが参考になれば幸いです!
デザイン考えるのってすごく難しくWebページ作ろう!と思っても毎回ここで時間をくってしまいます(泣)
こういった面白い動きのあるものをどんどん勉強して面白いWebページをつくっていきたいです!
最後まで読んでいただきありがとうございました!

Discussion