先日リリースされたPanda CSS、Tailwind CSSの対抗馬として注目を集めています。
書き味はEmotionとほぼ変わりませんが、ゼロランタイムCSS in JSというジャンルに分類され、すべてのCSSをビルド時に生成することでランタイムCSS in JSが抱えていたパフォーマンスの問題を解決しています。
Panda CSSはスタイルを動的に変更できない
一方デメリットとしては、すべてのスタイルが静的解析によって生成されるため、Emotionでは当たり前のように出来ていたJavaScriptを使った動的な変更ができないことが挙げられると思います。
本記事では、そんなPanda CSSでURLのパス(location)に応じてメニューバー中の現在のページの部分だけスタイルを変える一例を紹介します。
aria-current
とは
aria-current
は現在のページを表す属性で、主にスクリーンリーダーに該当の要素の意味を補強するために、アクセシビリティの観点から記述が推奨されている属性です。いくつかの値を取りますが、aria-current="page"
とすることで、現在のページを表すことができます。
CSSでaria-current="page"
が設定された要素を選択するには、[aria-current="page"]
というセレクタを利用しますが、Panda CSSでは_currentPage
というConditional Styleが用意されています。
実装
以下はNext.js v13のApp routerを利用した場合の実装方法です。usePathname
の部分を変えればReactやNext.js Pages routerでも同様に実装できると思います。
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { css } from "@panda/css";
export default function Menu() {
const pathname = usePathname();
const links = [
{ href: "/", label: "ホーム" },
{ href: "events", label: "滞在状況"},
{ href: "/history", label: "履歴" },
{ href: "/settings", label: "設定" },
];
return (
<>
{links.map(({ href, label }) => (
<Link
aria-current={pathname === href ? "page" : undefined}
className={css({
color: "inherit",
textDecoration: "none",
px: 4,
py: 2,
borderRadius: 8,
transition: "all 0.2s",
_hover: {
bgColor: "gray.200",
_osDark: {
bgColor: "gray.600",
},
},
_currentPage: {
color: "green.500",
},
})}
href={href}
key={href}
>
{label}
</Link>
))}
</>
);
}
おわり
Emotionを使っていると何かとJS側でスタイルの条件分岐をしてしまいがちですが、パフォーマンス的にはあまりよろしくないので、このようにできるだけCSS側で処理させてあげるようにすると良さそうです。