🎉
SP画面でメニューを表示するCSS 📱
cssで以下のような画面を作ることがよくあると思います!
今回はSP画面ということで、右の画面はpcをイメージしているので動きません
今回はこれの作り方を記事にします。
こういうcssで〇〇の作り方みたいな記事はZennであまりみないな🤔 と思って誰かの暇つぶしになれば!
対象者
- プログラミングが好き
- CSSで動くものを見るのが好き
実際のコード
React(react router v7) + Tailwindで実装しています
まずはドロップダウンする部分のコンポーネントを作成
type MobileDropdownItemsProps = {
onCloseMenu: () => void;
isMenuOpen: boolean;
};
const MobileDropdownItems = ({
onCloseMenu,
isMenuOpen,
}: MobileDropdownItemsProps) => {
const menuRef = useRef<HTMLDivElement>(null);
// メニュー外をクリックした時にもメニューが閉じるようにしたく実装
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
menuRef.current &&
!menuRef.current.contains(event.target as Node) &&
isMenuOpen
) {
onCloseMenu();
}
};
document.addEventListener("pointerdown", handleClickOutside);
return () => {
document.removeEventListener("pointerdown", handleClickOutside);
};
}, [onCloseMenu, isMenuOpen]);
return (
<div
ref={menuRef}
data-menu={isMenuOpen}
className={cn(
"md:hidden bg-slate-50 overflow-hidden fixed z-40 top-16 left-0 right-0 w-svw",
"transform ease-in-out -translate-y-full transition-transform shadow-md",
"duration-200 data-[menu=true]:translate-y-0"
)}
>
<ul className="flex flex-col gap-y-1 py-2 px-4 w-full">
<Item size="full" to="/" icon={LayoutDashboard}>
Top
</Item>
<Item size="full" to="list" icon={SquareCheck}>
一覧
</Item>
</ul>
</div>
);
};
# openしていない時は-translate-y-fullを使って画面外に移動させています
# data属性がtrueになったらこれに切り替えるようにすることで表示するようにしています
data-[menu=true]:translate-y-0
次にヘッダー部分とボタンを配置
cnは自作の関数で、tailwind-mergeのラッパー関数なので、イメージただ文字列を連結させてるだけです
const Header = () => {
const [isMenuOpen, handleIsMenuOpen] = useReducer((state) => !state, false);
return (
<div className="flex flex-col">
<header
className={cn(
"fixed z-50 top-0 left-0 right-0 h-14",
"flex items-center justify-start bg-background-header px-4 shadow",
"header-contents"
)}
>
<button className="text-gray-500" onClick={onOpenMenu}>
{isMenuOpen ? (
<X className="w-8 h-8" />
) : (
<AlignJustify className="w-8 h-8" />
)}
</button>
</header>
<MobileDropdownItems
onCloseMenu={handleIsMenuOpen}
isMenuOpen={isMenuOpen}
/>
</div>
)
}
まとめ
アニメーション周りって普段実装をする時に頻繁に出てくるものではないので、ちょっとした暇つぶしには丁度よかったのではないでしょうか!
Discussion
mousedown よりも pointerdown の方が良いのでは……?
確かに実機のこと考えるとpointerじゃないとですね😅
ありがとうございます!