logo

【コピペだけ!】Tailwind & Next.js(React) ハンバーガーメニュー完全レスポンシブ対応

【コピペだけ!】TAILWIND & NEXT.JS(REACT) ハンバーガーメニュー完全レスポンシブ対応...
プログラミング
目次
  • 使用したライブラリー

  • ファイル構成

  • 各ファイルのコード

  • 終わり

  • 前回のSassを使ったハンバーガーメニューUIの記事はこちら⬇︎

    今回の記事はコピペするだけで、完全レスポンシブ対応のハンバーガーメニューのコードを紹介。
    Next.js(React) & Tailwind CSS を使っていて、TypeScript の tsx ファイルにも対応しています。

    この記事のコードを使うことで、簡単にハンバーガーメニューを実装できるかと思います。

    デモサイトURL

    注意:これらのコードは 2024年7月の時点でのコードです。(下記機能がプロジェクトに沿う場合のみお使いください。)

    このハンバーガーメニューの機能一覧です:

    • 完全レスポンシブ対応
    • 現在のパスにリンクに背景色が付く
    • メニュー外をクリックするとメニューが閉じる

    使用したライブラリー

    • Tailwind CSSのみ

    ファイル構成

    app
      --  page.tsx
      --  Hamburger.tsx
      --  NavLinks

    各ファイルのコード

    page.tsx
    "use client";
    import Link from "next/link";
    import NavLinks from "./NavLinks";
    import Hamburger from "./Hamburger";
    
    const Header = () => {
      return (
        <header
          className={`bg-black text-white py-2 max-[480px]:py4 max-[480px]:px-4 px-6 z-10`}
        >
          <nav className="max-w-[1080px] mx-auto flex justify-between items-center max-[899px]:hidden">
            <Link href="/">
              <div
                className="textShadow_wt text-[2.2rem] font-bold text-nowrap max-[1000px]:text-[1.8rem] 
              hover:opacity-70 transition-all duration-300"
              >
                LOGO
              </div>
            </Link>
            <NavLinks />
          </nav>
          <Hamburger />
        </header>
      );
    };
    
    export default Header;
    
    
    Hamburger.tsx のコード
    "use client";
    import { useState } from "react";
    import Link from "next/link";
    import NavLinks from "./NavLinks";
    
    const Hamburger = () => {
      const [isMenuOpen, setIsMenuOpen] = useState(false);
      return (
        <nav className="relative z-10 pr-8 pl-2 py-2 flex justify-between items-center text-slate-950 min-[900px]:hidden ">
          <Link href="/">
            <div className="text-3xl font-bold leading-none">
              <div
                className="textShadow_wt mt-4 text-white font-bold text-nowrap max-[1000px]:text-[2.4rem] 
              max-[768px]:text-[2rem] max-[768px]:mt-2 max-[480px]:text-[1.7rem] max-[480px]:mt-1 "
              >
                LOGO
              </div>
            </div>
          </Link>
          <button
            className="navbar-burger flex items-center text-white p-3 flex-row-reverse flex-grow"
            onClick={() => setIsMenuOpen(!isMenuOpen)}
          >
            <svg
              className="block h-6 w-6 fill-current"
              viewBox="0 0 20 20"
              xmlns="http://www.w3.org/2000/svg"
            >
              <title>Mobile menu</title>
              <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
            </svg>
          </button>
          <div
            className={`${isMenuOpen ? "flex" : "hidden"} absolute top-1/2 left-1/2 transform -translate-y-1/2 -translate-x-1/2 lg:flex lg:mx-auto lg:items-center lg:w-auto lg:space-x-6`}
          ></div>
          {isMenuOpen && (
            <div className="navbar-menu relative z-50">
              <div
                className="navbar-backdrop fixed inset-0 bg-neutral-800 opacity-75"
                onClick={() => setIsMenuOpen(false)}
              ></div>
              <div className="fixed top-0 left-0 bottom-0 flex flex-col w-4/6 max-w-sm py-6 px-6 bg-neutral-950/90 overflow-y-auto">
                {/* Logo & Close button */}
                <div className="flex items-center mb-8">
                  <Link href="/">
                    <div className="mr-auto text-3xl font-bold leading-none">
                      <div className="textShadow_wt text-white text-[2.2rem] font-bold text-nowrap max-[1000px]:text-[1.4rem] ">
                      LOGO
                      </div>
                    </div>
                  </Link>
                  <button
                    className="navbar-close ml-14"
                    onClick={() => setIsMenuOpen(false)}
                  >
                    <svg
                      className="h-6 w-6 text-gray-400 cursor-pointer hover:text-gray-500"
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path d="M6 18L18 6M6 6l12 12"></path>
                    </svg>
                  </button>
                </div>
                <div>
                  <NavLinks setIsMenuOpen={setIsMenuOpen} />
                </div>
              </div>
            </div>
          )}
        </nav>
      );
    };
    
    export default Hamburger;
    
    NavLinks.tsx のコード
    "use client";
    import Link from "next/link";
    import { usePathname } from "next/navigation";
    
    type PropsType = {
      propClass?: string;
      setIsMenuOpen?: (arg0: boolean) => void;
    };
    
    const NavLinks = ({ propClass, setIsMenuOpen }: PropsType) => {
      const currentPath = usePathname();
    
      const links = [
        { label: "HOME", href: "/" },
        { label: "ABOUT", href: "/about" },
        { label: "CONTACT", href: "/contact" },
        { label: "SONGS", href: "/songs" },
        { label: "MERCH", href: "/merch" },
        { label: "ADMIN", href: "/admin", admin: true },
      ];
    
      return (
        <div
          className={`flex gap-3 mx-3 max-[899px]:flex-col max-[899px]:text-white 
          max-[899px]:gap-9 max-[767px]:w-[fit-content] max-[767px]:last:w-[70%] ${propClass}`}
        >
          {links
            .map((link) => (
              <Link
                //? Close hamburger menu
                onClick={() => setIsMenuOpen && setIsMenuOpen(false)}
                href={link.href}
                className={`w-[fit-content] hover:bg-slate-700 hover:text-primary/60 px-3 py-1 rounded-md text-sm font-medium cursor-pointer text-[1.1rem]
                ${link.admin && "bg-red-500 text-white"}
                ${
                  currentPath == link.href
                    ? "bg-slate-700 cursor-default shadow-1 text-primary/70 hover:text-primary/60 "
                    : ""
                }`}
                key={link.label}
              >
                {link.label}
              </Link>
            ))}
        </div>
      );
    };
    
    export default NavLinks;
    

    終わり

    今回は Tailwind & Next.js でハンバーガーメニューを実装しました。
    React のプロジェクトにも使用できるかと思います。

    以上、お役に立てれば幸いです。

    人気記事

    メルボルン移住(ワーホリ)を検討している方へ
    オーストリア
    メルボルン移住(ワーホリ)を検討している方へ
    メルボルンで絶対に行きたい場所10選
    オーストリア
    メルボルンで絶対に行きたい場所10選
    『ネイティブ監修』 オーストラリア厳選スラング30
    英語
    『ネイティブ監修』 オーストラリア厳選スラング30
    海外のWEBエンジニア特化スクールの費用や授業内容や費用など完全解説(オーストラリア・メルボルン)
    オーストリア
    海外のWEBエンジニア特化スクールの費用や授業内容や費用など完全解説(オーストラリア・メルボルン)
    • Kazu

      Kazu

      オーストラリア在住歴7年。現地で英語学習後に日本語教師 → 工場就職 → 海外WEB開発ディプロマを取得→フリーランス。現在は余った時間をプログラミング&ブログに費やして生きています。

    13