YuTa Extend

オリジナル楽曲とIT系個人開発紹介のブログ

【Next.js】「トップへ戻るボタン」を実装する

  2022-12-22

【Next.js】「トップへ戻るボタン」を実装する

「トップへ戻るボタン」を実装する

Next.js で定番ブログパーツである「トップへ戻るボタン」を実装します。 Styled-JSX で CSS をコンポーネント内に入れ込むため、このコードをそのままどのサイトにも流用できます。

「トップへ戻るボタン」とは

「トップへ戻るボタン」とは、押すとページの一番上にスクロールするボタンです。 最近は縦に長いページが多く、スクロールの手間を減らすために右下に置いているサイトがよく目につきます。

少しスクロールしたらボタンを表示するようにする

フックを使うと、スクロール量を検知することができます。 これを利用して、少しスクロールしたらボタンを表示するようにします。

ボタンのアイコンは react-icons で作ります。使い方については、前回の記事を参照ください。

また、ボタン自体を画面右下に固定するには、CSS のposition: fixed;を使います。

BackToTopButton.tsx
Copied!!
import { BiChevronsUp } from "react-icons/bi";
import { useEffect, useState } from "react";

const BackToTopButton: React.FC = () => {
  const [isButtonActive, setIsButtonActive] = useState(false);

  useEffect(() => {
    window.addEventListener("scroll", scrollWindow);
    return () => {
      window.removeEventListener("scroll", scrollWindow);
    };
  }, []);

  const scrollWindow = () => {
    const top = 100; //ボタンを表示させたい位置
    let scroll = 0;
    scroll = window.scrollY;
    if (top <= scroll) {
      setIsButtonActive(true);
    } else {
      setIsButtonActive(false);
    }
  };

  const normalStyle = {
    opacity: 0,
    transition: "0.5s",
    pointerEvents: "none",
  };
  const activeStyle = {
    opacity: 1,
    transition: "0.5s",
  };
  const style = isButtonActive ? activeStyle : normalStyle;

  return (
    <>
      <div id="back-to-top-btn" style={style}>
        <BiChevronsUp size="2rem" color="white" />
      </div>
      <style jsx>{`
        #back-to-top-btn {
          position: fixed;
          bottom: 20px;
          right: 20px;
          z-index: 10000;
          background-color: #333;
          border-radius: 4rem;
          padding: 0.6rem;
          box-shadow: 0 2px 8px #4385bb88;
        }
        #back-to-top-btn:hover {
          cursor: pointer;
        }
      `}</style>
    </>
  );
};

export default BackToTopButton;

react-scroll でデバイスに依存しないスムーススクロールを実装する

スクロールを JavaScript で実装する際、デバイスや OS によっては特別な書き方を求められる場合があります。 react-scroll というプラグインを使うと、どのデバイスや OS でも同じ書き方でスクロールを実装できます。

以下のコマンドで react-scroll をインストールします。

Copied!!
> npm i react-scroll
> npm i --save-dev @types/react-scroll
BackToTopButton.tsx
Copied!!
import { animateScroll as scroll } from "react-scroll";
import { BiChevronsUp } from "react-icons/bi";

const BackToTopButton: React.FC = () => {
  const scrollToTop = () => {
    scroll.scrollToTop();
  };
  return (
    <>
      <div id="back-to-top-btn" onClick={scrollToTop}>
        <BiChevronsUp size="2rem" color="white" />
      </div>
      <style jsx>{`
        #back-to-top-btn {
          position: fixed;
          bottom: 20px;
          right: 20px;
          z-index: 10000;
          background-color: #333;
          border-radius: 4rem;
          padding: 0.6rem;
          box-shadow: 0 2px 8px #4385bb88;
        }
        #back-to-top-btn:hover {
          cursor: pointer;
        }
      `}</style>
    </>
  );
};

export default BackToTopButton;

まとめ

最終的には以下のようになりました。

BackToTopButton.tsx
Copied!!
import { animateScroll as scroll } from "react-scroll";
import { BiChevronsUp } from "react-icons/bi";
import { useEffect, useState } from "react";

const BackToTopButton: React.FC = () => {
  const scrollToTop = () => {
    scroll.scrollToTop();
  };

  const [isButtonActive, setIsButtonActive] = useState(false);

  useEffect(() => {
    window.addEventListener("scroll", scrollWindow);
    return () => {
      window.removeEventListener("scroll", scrollWindow);
    };
  }, []);

  const scrollWindow = () => {
    const top = 100; //ボタンを表示させたい位置
    let scroll = 0;
    scroll = window.scrollY;
    if (top <= scroll) {
      setIsButtonActive(true);
    } else {
      setIsButtonActive(false);
    }
  };

  const normalStyle = {
    opacity: 0,
    transition: "0.5s",
    pointerEvents: "none",
  };
  const activeStyle = {
    opacity: 1,
    transition: "0.5s",
  };
  const style = isButtonActive ? activeStyle : normalStyle;

  return (
    <>
      <div id="back-to-top-btn" style={style} onClick={scrollToTop}>
        <BiChevronsUp size="2rem" color="white" />
      </div>
      <style jsx>{`
        #back-to-top-btn {
          position: fixed;
          bottom: 20px;
          right: 20px;
          z-index: 10000;
          background-color: #333;
          border-radius: 4rem;
          padding: 0.6rem;
          box-shadow: 0 2px 8px #4385bb88;
        }
        #back-to-top-btn:hover {
          cursor: pointer;
        }
      `}</style>
    </>
  );
};

export default BackToTopButton;

まとめ

今回は定番ブログパーツである「トップへ戻るボタン」を実装しました。 Styled-JSX で CSS をコンポーネント内に入れ込んでいるため、このコードをそのままどのサイトにも流用できます。

参考文献

関連記事