🐼

次世代のCSS in JS、Panda CSSをNext.js Appルーターで使用する

2023/06/23に公開

はじめに

Panda CSSはゼロランタイムで型安全、かつ高いDXを持ったCSS in JSライブラリです。

React Server Componentsの登場により、Emotionやstyled-componentsといったランタイムCSS in JSライブラリの見直しが必要になりつつあります。
Panda CSSはEmotionに依存しているChakra UIというUIコンポーネントライブラリがReact Server Componentsに対応するために独自開発したゼロランタイムCSS in JSライブラリです。

上記でReact Server Componentsの話が出たものの、Panda CSSは特定のUIライブラリを選ばず、多くのUIライブラリに対応しており、その点も魅力的です。
https://panda-css.com/docs#framework-guides

また、Panda CSSは以下に挙げているこれまでの様々なCSSライブラリからインスピレーションを得ていると公式ドキュメントで言及している通り、まさにこれまでの様々なCSSライブラリのいいとこ取りのようなCSS in JSライブラリになっています。

  • Chakra UI
  • Vanilla Extract
  • Stitches
  • Tailwind CSS
  • Class Variance Authority
  • Styled System
  • Linaria
  • Uno CSS

https://panda-css.com/docs#acknowledgement

Panda CSSをNext.js Appルーターで使用する

それではPanda CSSを触ってみましょう。

今回はNext.js Appルーターと一緒に使用してみます。
公式ドキュメントに丁寧なGetting Startedが用意されているのでそちらに沿って進めていきます。

create-next-appでNext.jsプロジェクトの雛形を作成

以下のコマンドを実行します。

npx create-next-app@latest --use-npm

いくつか対話式の質問がありますが、任意の回答をしてください。
この記事ではTypeScriptあり、srcディレクトリありを想定しています。

Panda CSSをインストール

以下のコマンドを実行します。

npm install -D @pandacss/dev

続いて設定ファイルを自動生成します。

npx panda init --postcss

プロジェクトルートにpanda.config.tspostcss.config.cjsが生成されます。

npm scriptsを追加

以下のようにpackage.jsonを修正します。

package.json
{
  "scripts": {
+    "prepare": "panda codegen",
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}

npm installの後にpanda codegenが実行されるようになりますが、今回は手動でnpx panda codegenを実行しましょう。

panda codegenによってpanda.config.tsをもとにデフォルトではプロジェクトルートのstyled-systemディレクトリにCSSユーティリティが生成されます。

この生成されたCSSユーティリティはGitで管理する必要はないので、以下のように.gitigonoreを修正します。

.gitigonore
...
+ # panda css
+ styled-system

開発者はこの生成されたCSSユーティリティを使用してスタイリングを行います。

エントリーポイントとなるCSSを追加

今回はglobals.cssをエントリーポイントとなるCSSとして使用します。
以下のように修正します。その他のCSSは不要なので削除してOKです。

src/app/globals.css
@layer reset, base, tokens, recipes, utilities;

このCSSではカスケードレイヤーを定義しています。
https://panda-css.com/docs/concepts/cascade-layers

上記のCSSをルートレイアウトでimportする

以下のようにルートレイアウトを修正します。

src/app/layout.tsx
import "./globals.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

CSSユーティリティを使用してスタイリング

以下のようにホームページを修正します。

src/app/page.tsx
import { css } from "../../styled-system/css";

export default function Page() {
  return (
    <main>
      <h1 className={css({ fontSize: "2xl", fontWeight: "bold" })}>
        Hello 🐼!
      </h1>
    </main>
  );
}

"use client";の記述がないことからReact Server Componentsに対応していることが分かりますね。

npm run devで開発サーバーを立ち上げ、http://localhost:3000/を開くとリセットCSSと上記で指定したスタイルが適用されていることが確認できると思います。

Chrome DevToolsを開いて要素を確認すると、h1fs_2xl font_boldというclassが付与されていると思います。
CSSユーティリティのcss関数は引数にSystemStyleObjectを受け取り、単なる文字列(class)を返していることと1プロパティが1classに対応していることが分かりますね。

本番ビルドを作成

最後に本番ビルドを作成してみましょう。
以下のコマンドを実行します。

npm run build

.next/static/cssを開くと、最終的なCSSが生成されていることが確認できると思います。
minifyされているので見にくいですが、fs_2xlfont_boldで検索してみると、定義したスタイルがutilitiesレイヤー(優先度が一番高い)に存在していることが分かりますね。

Panda CSSの仕組み

上記からPanda CSSの仕組みをざっくりとまとめると以下のようになります。

  1. panda codegenによってCSSユーテリティを生成
  2. 生成されたCSSユーティリティを使用してスタイリング
  3. ビルド時に最終的なCSSを生成

全体的にはTailwind CSSの仕組みと似ていますが、CSSユーテリティという中間コードのようなものが生成され、それを使用してスタイリングを行うという点はユニークだと思います。

Panda CSSのコンセプト

サイボウズのmugiさんの記事で丁寧に説明されているので、そちらか公式ドキュメントを読んでみてください。
https://zenn.dev/cybozu_frontend/articles/panda-is-coming
https://panda-css.com/docs/concepts/cascade-layers

おわりに

いかがだったでしょうか。
これまでの様々なCSSライブラリのいいとこ取りのようなCSS in JSライブラリと書きましたが、まさにといった感じで、使いこなすのは大変そうですが、今後特にNext.js Appルーターを使用するプロジェクトでは技術選定の選択肢に入ってくるのではないでしょうか。
また、個人的にはこれまではTailwind CSSを選定していたケースで代わりに選定することも増えてくるのではないかと思っています。

公式ドキュメントが非常に充実していますので、ぜひ一度目を通してみてください。
https://panda-css.com/

Discussion