Panda CSSとは?型付きスタイル生成の設定と採用判断を実装目線で解説
Panda CSSは、TypeScriptで書いたスタイル定義をビルド時に読み取り、そこからアトミックCSSを生成するスタイリングエンジンです。Chakra UIと同じchakra-ui/pandaリポジトリで開発されており、npm registryで2026年8月12日に確認した@pandacss/devのlatestは1.12.0(公開日は2026年7月29日)、並行してv2系が2.0.0-beta.13まで進んでいました。この記事では、Panda CSSの立ち位置、Viteでのnpm導入とpanda.config.tsの各項目、cvaとconfig recipeの出力差、静的解析で拾えないランタイム値の扱い、そしてTailwind CSSやUnoCSSと比べて受託開発で採用してよい条件までを実装目線で扱います。
まとめ:Panda CSSを採用してよい条件と見送る線引き
結論から置きます。ReactやSolidでコンポーネントを組み、スタイルをTypeScriptの型に載せて管理したい。しかも実行時にCSSを注入するオーバーヘッドは持ち込みたくない。この2つが同時に要求される案件なら、Panda CSSはよく噛み合います。生成されたstyled-systemディレクトリ経由でトークン名やバリアント名が補完され、存在しないトークンを書けばビルド前に型エラーになる。CSS-in-JSの書き味を保ったまま、出力はアトミックなクラス列になります。
見送る判断が要るのは3つの場面。第一に、ビルド工程を触れないプロジェクト。Panda CSSはpanda codegenで生成物を作ることが前提で、CDNから読み込んで終わりという使い方はできません。第二に、スタイル値をAPIレスポンスやユーザー設定から実行時に決める設計。静的解析で拾えない値はCSSが出力されず、staticCssでの事前列挙という追加運用が乗ります。第三に、フロントエンド専任がいない少人数の保守体制。設定ファイルと生成物の両方を理解する前提のツールなので、学習コストが恩恵を上回ります。
Panda CSSの定義|ビルド時に型付きCSSを生成するスタイリングエンジン
まず、Panda CSSが何を解いているのかを押さえます。ここを取り違えると「Tailwindの型付き版」という理解で入り、生成ディレクトリの存在に戸惑うことになります。
CSS-in-JSの書き味とアトミックCSS出力を両立させる静的解析
公式ドキュメントはPanda CSSを「型安全で読みやすい形でアトミックCSSとレシピを記述するための、スタイリングプリミティブを生成するスタイリングエンジン」と定義しています。同じ箇所で、CSS-in-JSの開発体験とアトミックCSSの性能を組み合わせるものだと説明されている点が肝。実現手段は静的解析で、JavaScriptとTypeScriptのファイルを走査し、JSXのスタイルpropsと関数呼び出しを見つけてオンデマンドにCSSを作ります。
この構造の帰結として、実行時にスタイルを組み立てるコードはバンドルに残りません。styled-componentsのように実行時にCSSを注入する方式とは、性能特性も引き継ぎ時の注意点も別物になります。実行時CSS-in-JSの現在地についてはstyled-componentsのメンテナンスモード後の状況を整理した記事も参考になるはずです。
styled-systemディレクトリを生成してから使うcodegen前提
Panda CSSは、インストール直後には何も書けません。panda codegenを走らせてoutdir(既定値はstyled-system)に関数と型を生成し、そこからimportして初めてスタイルが書けるようになります。公式のVite手順がpackage.jsonのprepareスクリプトにpanda codegenを置くよう案内しているのは、依存インストール直後に生成物を揃えるためです。
生成物はリポジトリにコミットしない運用が素直で、その場合は.gitignoreにstyled-systemを足し、CIとローカルの双方でprepareが走る状態を作ります。ここを曖昧にしたまま新メンバーがクローンすると、import先が存在せず型エラーの山から始まる。導入初期にいちばん起きやすい躓きです。
Viteでのnpm導入とpanda.config.tsで決める設定項目
公式が推奨しているのはPostCSS経由の統合で、CLIのpanda init --postcssが設定ファイルをまとめて用意します。ここではVite構成を例に、手順と設定値の決め方を追います。
panda init –postcssから初回ビルドまでの6工程
Viteプロジェクトへの導入は、公式ドキュメントの手順どおりに進めると次の並びになります。
npm install -D @pandacss/devで開発依存として追加するnpx panda init --postcssを実行し、設定ファイルとPostCSS設定を生成するpackage.jsonのprepareにpanda codegenを登録するpanda.config.tsのincludeを自分のディレクトリ構成に合わせる- CSSエントリに
@layer reset, base, tokens, recipes, utilities;を1行書く tsconfig.jsonのincludeに生成先ディレクトリを足す
6番目を飛ばすと、生成物の型がエディタから見えず補完が効きません。公式手順では"include": ["src", "styled-system"]という形で、ソースと生成先の両方を並べるよう指示されています。
include・exclude・outdir・jsxFrameworkの決め方
初期生成されるpanda.config.tsはpreflight、include、exclude、jsxFramework、outdirの5項目で構成されます。実務で手を入れる頻度が高いのはincludeで、既定値は./src/**/*.{js,jsx,ts,tsx}と./pages/**/*.{js,jsx,ts,tsx}という2パターン。componentsやfeaturesをルート直下に置く構成では、この2つのどちらにも当たらずCSSが出ないという事故が起きます。
jsxFrameworkはreactのほかSolidやVueなどを指定でき、値に応じてstyled系のJSXコンポーネントが生成されます。JSXのスタイルpropsを使わずcss関数だけで書くなら、この項目を外して生成物を軽くする手もある。outdirを既定のstyled-systemから変えるのは、モノレポで生成物を共有したいときくらいでしょう。
@layerの並び順とpreflightで変わる打ち消しの順序
CSSエントリに書く@layer reset, base, tokens, recipes, utilities;は、単なるおまじないではありません。CSSカスケードレイヤーの宣言順がそのまま優先順位になるため、この行の順番を入れ替えるとリセットがユーティリティを打ち消す、といった逆転が起きます。既存のCSS資産と併存させる場合は、この宣言行より前に自前のレイヤーを差し込むか、レイヤー外に置くかで挙動が変わる点に注意します。
preflight: trueはブラウザ既定スタイルのリセットをresetレイヤーへ流し込む設定。既存サイトへ部分導入するときはfalseにしておかないと、Panda CSSを使っていない画面の見た目まで変わります。スコープの切り方という観点では、CSS Modulesのスコープ機構と型安全化の設定と比べると設計思想の差が見えやすいでしょう。
cvaとconfig recipeの出力差とスロットレシピの守備範囲
Panda CSSでコンポーネントのバリアントを定義する道は2本あり、生成されるCSSの量が違います。この差を知らずに選ぶと、使っていないバリアントのCSSを本番へ配ることになります。
cvaは全バリアント生成・config recipeはJITという出力差
cvaで書くアトミックレシピは、コンポーネントファイルの隣に置けるのが利点です。実行時に.raw()やcss()と組み合わせたマージも可能です。ただし公式ドキュメントが明記しているとおり、宣言したバリアントは使用状況にかかわらずすべて生成されます。5サイズ×4色のボタンをcvaで定義すれば、実際に使うのが2通りでも20通り分のクラスが出ます。
theme.recipesにdefineRecipeで置くconfig recipeは逆で、コードから検出したバリアントぶんだけを出力するJIT方式。ドキュメントは「使用したレシピとバリアントだけが生成後のCSSに存在する」と書いています。プリセットとしてチーム内に配布できるのもconfig recipe側の性質です。複数の要素にまたがるコンポーネント(モーダルの背景・本体・閉じるボタンなど)は、スロットレシピで部位ごとにスタイルをまとめます。
config recipeのjsxプロパティで使用箇所を追跡させる設定
config recipeにはjsxプロパティがあり、追跡対象にしたいコンポーネント名を配列で渡します。レシピ名と同じ名前のコンポーネントは自動で検出されますが、PrimaryButtonのように別名でラップした場合は明示しないと検出から漏れます。漏れた結果はビルドエラーではなくスタイル欠落として現れるため、原因の切り分けに時間を取られがちです。
もうひとつ、config recipeはレスポンシブなバリアントpropsに対応しますが、compoundVariantsを設定している場合は対象外になります。ブレークポイントごとにサイズを変える設計と、複合条件でスタイルを分岐させる設計は、同じレシピの中で両立しません。Tailwind系で同じ課題をどう解いているかはTailwind Variantsのslotsとレスポンシブ対応の整理が対照になります。
静的解析で拾えないランタイム値とstaticCssによる回避策
Panda CSSでいちばん詰まるのがここです。ビルド時にCSSを決める以上、実行時にしか値が分からないスタイルは原理的に生成できません。
useStateの値をcssへ渡すとCSSが出ない失敗パターン
公式ドキュメントは、ビルド時に静的解析できない値はPanda CSSでは動作しないと明言し、具体例として次の形を挙げています。const [color, setColor] = useState('red.300')で得た値をcss({ color })に渡すコードです。TypeScriptの型は通り、ビルドも成功する。それでも該当するCSSクラスは生成されず、本番で色が当たりません。
この挙動は、テーマ切り替えやユーザー設定で色を変える機能を後から足したときに露見します。開発中は既存クラスの巻き添えで気づかず、本番デプロイ後に一部の画面だけ崩れる。原因がスタイル指定ではなく抽出範囲にあるため、CSSファイルを開いても該当クラスが見つからないという形で現れます。
staticCss・token()・data属性という3つの逃がし方
公式が案内している回避策は次のとおりで、上から順に検討すると設計が崩れにくくなります。
staticCssに候補値を列挙し、使う可能性のあるスタイルを事前生成しておくtoken()でCSSカスタムプロパティに値を入れ、CSS側は変数参照だけにする- 状態を
data-*属性へ移し、属性セレクタでスタイルを分岐させる - 候補が有限ならレシピのバリアントへ寄せ、型で選択肢を縛る
実務で最初に試すべきは4番目です。色やサイズの候補が実は10通りしかないなら、レシピのバリアントに落とせば型の恩恵も残ります。staticCssは候補が増えるほど出力CSSが膨らむため、真に自由な値(ユーザーが入力したカラーコードなど)にだけtoken()とCSS変数を使う、という切り分けが現実的でしょう。ドキュメント自身も、ランタイム値に依存しない設計を推奨する立場を取っています。
v1.12.0系とv2.0.0ベータで変わる構成とNode要件
導入判断の前に、いま2系統が並走している事実を把握しておく価値があります。ここは日本語の解説記事がほぼ触れていない領域です。
PostCSS中心のv1とバンドラプラグイン中心のv2の構成差
npm registryで2026年8月12日に見たところ、@pandacss/devのlatestは1.12.0(2026年7月29日公開)、betaタグは2.0.0-beta.13(2026年8月11日公開)でした。v1.0.0の公開が2025年8月5日、2.0.0-beta.1が2026年6月17日なので、v2の開発は約2か月動き続けている計算になります。
| 観点 | v1.12.0系 | v2.0.0ベータ |
|---|---|---|
| 主な統合方式 | PostCSSプラグイン | バンドラ別プラグイン |
| 中核パッケージ | pandacss/node | pandacss/compiler |
| Node要件 | 20.12.0以上 | 22以上 |
| 初出 | 2023年2月 | 2026年6月 |
| ライセンス | MIT | MIT |
v2で新設されたパッケージ群(@pandacss/compiler、@pandacss/vite、@pandacss/webpack、@pandacss/rollup)は、npm registry上の作成日がいずれも2026年6月15日で、v1には存在しません。@pandacss/typescript-pluginに至っては2026年7月17日の作成です。PostCSSを挟む構成から、バンドラのプラグインとして直接組み込む構成へ、統合レイヤーごと作り替えられていると読めます。
Node.js要件が20.12.0以上から22以上へ上がる影響
@pandacss/devのenginesフィールドは、1.12.0がnode >=20.12.0、2.0.0-beta.13がnode >=22でした。CIランナーやDockerイメージのNodeを20系で固定している現場では、v2への移行がツール単体の入れ替えでは済みません。
いま新規に入れるなら、安定版の1.12.0を選ぶのが妥当な判断です。ベータは日次に近い頻度で更新が続いており、公開日が昨日という状態のパッケージを長期保守前提の案件に載せる理由が薄い。逆に、Node 22以上で組む短命なプロダクトや社内ツールで、バンドラ統合の速度改善を先に取りに行くなら、beta段階でも試す価値はあります。判断材料は流行ではなくNodeの固定状況です。
Tailwind CSS・UnoCSS・StyleXとの違いと受託での採用条件
同じ「ビルド時にCSSを作る」系でも、抽出の起点が違えば書き味も引き継ぎ性も変わります。並べて整理したうえで、採用の線を引きます。
Panda CSSと3系統の生成タイミング・抽出起点の守備範囲
| ライブラリ | 生成タイミング | 抽出の起点 | 型の効き方 |
|---|---|---|---|
| Panda CSS | ビルド時 | 関数呼び出しとprops | 生成コードで効く |
| Tailwind CSS | ビルド時 | クラス名の文字列 | IDE拡張の補完のみ |
| UnoCSS | ビルド時 | クラス名の文字列 | プリセット依存 |
| StyleX | ビルド時 | API呼び出し | 型定義で効く |
| styled-components | 実行時 | 実行時のCSS注入 | テンプレート内は弱い |
Panda CSSとStyleXは関数呼び出しを起点にする点で近い系統で、詳細はMeta製CSS-in-JSであるStyleXの導入手順と比べると差が掴めます。対してクラス名の文字列を起点にするのがTailwind CSSとアトミックCSSエンジンのUnoCSSで、こちらはHTMLだけを見ればスタイルが分かる代わりに、トークン名の誤記をビルド前に止められません。
受託開発でPanda CSSを採用してよい条件と見送る3つの場面
採用してよいのは、次の3条件が揃うときです。TypeScriptで書いている。デザイントークンを一元管理したい要求が発注側にある。そしてビルド設定をこちらで握れる。この3つが揃うなら、トークン名の誤記がビルド前に落ちる利点が保守フェーズまで効き続けます。
見送るべき場面も具体に落とします。第一に、CMSテーマや既存サイトへの部分適用。生成物とレイヤー宣言の追加が必要で、割に合いません。第二に、スタイル値を管理画面から可変にする要件が中心の案件。staticCssの列挙が仕様変更のたびに増え、運用が破綻します。第三に、納品後の改修を発注側の非専任担当が行う前提の案件。styled-systemの生成という前提を引き継げず、npm installだけで動かないという問い合わせに変わります。この3つでは、素直にTailwind CSSを選ぶほうが総コストは下がります。
引き継ぎ前提の受託案件で先に決めておく運用ルールと相談の進め方
Panda CSSを入れる案件では、コードを書き始める前に3点を文書化しておくと引き継ぎ事故が減ります。生成物をコミットするかどうか、staticCssに何を載せてよいかの基準、そしてNodeのバージョン固定値。とくに3点目は、v2がNode 22以上を要求する以上、将来の移行可否を左右します。
選定そのものは終わっていても、既存の業務画面をどう作り替えるか、どの範囲までフロントを刷新するかで手が止まる場面も珍しくないものです。当社では業務システムのフロントエンド刷新を含む業務用・Webアプリ開発を受託しており、技術選定の妥当性検証から実装・引き継ぎ資料の整備まで一貫して対応できます。既存資産を残したまま段階的に切り替える設計も含め、現状の構成を前提に相談いただけます。
よくある質問
Panda CSSの導入検討でよく挙がる論点を、公式ドキュメントとnpm registryの実測値をもとに整理します。
Panda CSSはゼロランタイムのCSS-in-JSですか?
スタイルの生成という観点では、そのとおりです。JavaScriptとTypeScriptのファイルを静的解析してビルド時にCSSを出力するため、実行時にスタイルを組み立ててDOMへ注入する処理は走りません。ただしクラス名を結合する軽量なヘルパーは実行時に動くので、JavaScriptが完全にゼロになるわけではない点は押さえておいてください。CSS-in-JSの書き味とアトミックCSSの出力特性を組み合わせる、という位置づけが実態に近い説明になります。
Panda CSSとTailwind CSSはどちらを選ぶべきですか?
判断軸はチーム構成です。TypeScriptで書き、デザイントークンの誤記を型で止めたいならPanda CSS。HTMLを直接触るデザイナーや非専任の担当者が保守に入るならTailwind CSSを選びます。Tailwind CSSはクラス名の文字列がそのままスタイルなので、生成物やcodegenという概念を引き継ぐ必要がありません。日本語情報の量と、既存のUIキット資産の多さもTailwind CSS側に分があります。
Next.jsでもVite向けの手順がそのまま使えますか?
大枠は同じで、npm install -D @pandacss/devとnpx panda init --postcss、prepareへのpanda codegen登録という流れは共通です。違いはincludeのパスとCSSエントリの置き場所で、App Routerならapp配下を含める必要があります。公式ドキュメントはNext.js、Vite、Astro、Remix、Vue、Svelteなど十数種のフレームワーク別ガイドを用意しているため、対象環境のページを直接参照するのが確実です。
panda.config.tsを変更したら再起動が必要ですか?
設定変更のうち、生成物の形に影響するもの(jsxFrameworkやoutdir、トークン定義の追加など)はpanda codegenの再実行が要ります。開発サーバーを起動したままtheme.tokensへ新しい色を足しても、生成された型に反映されるまでは補完に出てきません。includeの変更も同様で、監視対象の再構築が必要になります。設定を触ったら生成をやり直す、と手順化しておくと迷いません。
Panda CSSのv2はいつから本番で使えますか?
2026年8月12日時点でv2はベータ段階で、npm registryのbetaタグは2.0.0-beta.13、公開日は2026年8月11日でした。latestタグは1.12.0のままです。本番投入の目安は、latestタグが2系に移り、バンドラ別プラグインのドキュメントが整うタイミングになります。Node 22以上という要件も先に満たしておく必要があるため、CIイメージの更新計画とあわせて検討してください。