🎉

SP画面でメニューを表示するCSS 📱

2025/02/14に公開2

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