今回は、React(TypeScript)とTailwindでハンバーガーメニューを作ってみました。
個人開発でTailwindを使ってフロント部分を作っているのですが、素のCSSであれば簡単にできていたことが意外とTailwindを使うとどうやるんだっけということが多いので、まとめておきます。
本記事の信頼性
30歳から異業種への転職をして、Shopify Experts企業で1年半ほどフルリモートで勤務していました。
現在は名古屋の自社開発企業のフロントエンドエンジニアしています。フリーランスとしても活動しています。
最終的なコード
実装コード(クリックするとコードが表示されます)
import './styles.css';
import React, { useState } from 'react';
export default function App() {
const [openMenu, setOpenMenu] = useState(false);
const handleMenuOpen = () => {
setOpenMenu(!openMenu);
};
return (
<div className="App">
<div className="container mx-auto px-3">
<header className="flex justify-between py-3">
<h1>ロゴ</h1>
{/* humbergerbutton */}
<button onClick={handleMenuOpen} type="button" className="z-10 space-y-2">
<div
className={
openMenu
? 'w-8 h-0.5 bg-gray-600 translate-y-2.5 rotate-45 transition duration-500 ease-in-out'
: 'w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out'
}
/>
<div
className={
openMenu
? 'opacity-0 transition duration-500 ease-in-out'
: 'w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out'
}
/>
<div
className={
openMenu
? 'w-8 h-0.5 bg-gray-600 -rotate-45 transition duration-500 ease-in-out'
: 'w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out'
}
/>
</button>
{/* nav */}
<nav
className={
openMenu
? 'text-left fixed bg-slate-50 right-0 top-0 w-8/12 h-screen flex flex-col justify-start pt-8 px-3 ease-linear duration-300'
: 'fixed right-[-100%] ease-linear duration-300'
}
>
<ul className="mt-6">
<li className="">
<a href="https://okalog.info/" className="py-2 inline-block">
ABOUT
</a>
</li>
<li className="">
<a href="https://okalog.info/" className="py-2 inline-block">
WORKS
</a>
</li>
<li className="">
<a href="https://okalog.info/" className="py-2 inline-block">
PEOPLE
</a>
</li>
<li className="">
<a href="https://okalog.info/" className="py-2 inline-block">
CONTACT
</a>
</li>
</ul>
</nav>
</header>
{/* ここ以下はメインビジュアル用のコード */}
<main>
{/* MainVisual */}
<div className="mt-10">
<div className="mx-auto w-full">
<img
src="https://okalog.info/wp-content/uploads/sample/scenery/scenery_01.jpg"
alt=""
className="w-full rounded-3xl object-cover"
/>
</div>
</div>
</main>
</div>
</div>
);
}
実装方法
今回はReact(TypeScript)とTailwindが動作する環境は既にある前提で進めていきます。
ヘッダーを作成する
まずは、ヘッダー部分を作成します。
シンプルにロゴとハンバーガーメニューだけが存在するヘッダーとします。
ハンバーガーメニューは
<header className="flex justify-between py-3">
<h1>ロゴ</h1>
<button type="button" className="z-10 space-y-2">
<div className="w-8 h-0.5 bg-gray-600" />
<div className="w-8 h-0.5 bg-gray-600" />
<div className="w-8 h-0.5 bg-gray-600" />
</button>
</header>
オープン・クローズの挙動を作成する
次に、ハンバーガーメニューをクリックしたときにナビゲーションが表示される部分をReactで実装していきます。
useState
を使って表示・非表示を切り替えます。
button要素にonClick={handleMenuOpen}
を付与して、true/false
を切り替えができるようにします。
次に、openMenu
がtrue/false
のときにCSSを出し分けを行います。
三項演算子を使って実現することができます。
{openMenu ? "trueのとき" : "falseのとき" }
ハンバーガーメニューとナビゲーション要素で使用しています。
function App() {
const [openMenu, setOpenMenu] = useState(false);
const handleMenuOpen = () => {
setOpenMenu(!openMenu);
};
return (
<div className="App">
<div className="container mx-auto px-3">
<header className="flex justify-between py-3">
<h1>ロゴ</h1>
{/* humbergerbutton */}
<button onClick={handleMenuOpen} type="button" className="z-10 space-y-2">
<div className={openMenu ? 'w-8 h-0.5 bg-gray-600 translate-y-2.5 rotate-45' : 'w-8 h-0.5 bg-gray-600'} />
<div className={openMenu ? 'opacity-0' : 'w-8 h-0.5 bg-gray-600'} />
<div className={openMenu ? 'w-8 h-0.5 bg-gray-600 -rotate-45' : 'w-8 h-0.5 bg-gray-600'} />
</button>
{/* nav */}
<nav
className={
openMenu
? 'text-left fixed bg-slate-50 right-0 top-0 w-8/12 h-screen flex flex-col justify-start pt-8 px-3'
: 'fixed right-[-100%]'
}
>
<ul className="mt-6">
// 省略
</ul>
</nav>
</header>
</div>
</div>
);
}
アニメーションをつける
現状ですと、すぐに切り替わってしまうのでCSSのtransition
を付与します。
参考→ Transition Property
export default function App() {
const [openMenu, setOpenMenu] = useState(false);
const handleMenuOpen = () => {
setOpenMenu(!openMenu);
};
return (
<div className="App">
<div className="container mx-auto px-3">
<header className="flex justify-between py-3">
<h1>ロゴ</h1>
{/* humbergerbutton */}
<button
onClick={handleMenuOpen}
type="button"
className="z-10 space-y-2"
>
<div
className={
openMenu
? "w-8 h-0.5 bg-gray-600 translate-y-2.5 rotate-45 transition duration-500 ease-in-out"
: "w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out"
}
/>
<div
className={
openMenu
? "opacity-0 transition duration-500 ease-in-out"
: "w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out"
}
/>
<div
className={
openMenu
? "w-8 h-0.5 bg-gray-600 -rotate-45 transition duration-500 ease-in-out"
: "w-8 h-0.5 bg-gray-600 transition duration-500 ease-in-out"
}
/>
</button>
{/* nav */}
<nav
className={
openMenu
? "text-left fixed bg-slate-50 right-0 top-0 w-8/12 h-screen flex flex-col justify-start pt-8 px-3 ease-linear duration-300"
: "fixed right-[-100%] ease-linear duration-300"
}
>
<ul className="mt-6">
//省略
</ul>
</nav>
</header>
{/* ここ以下はメインビジュアル用のコード */}
<main>
{/* MainVisual */}
<div className="mt-10">
<div className="mx-auto w-full">
<img
src="https://okalog.info/wp-content/uploads/sample/scenery/scenery_01.jpg"
alt=""
className="w-full rounded-3xl object-cover"
/>
</div>
</div>
</main>
</div>
</div>
);
}
最終的にはこの状態になります。
まとめ
Tailwindですが、どんあクラスが用意されているのかを調べるのが毎回時間かかってしまいますがやっていれば慣れてくるのかなーという思いで触っております。
今後もTailwindを使った実装をしていく予定ですよので、学んだことがあればブログにして発信していきます。
こちらオススメのUdemyの学習教材です!^^