---
title: "Panda CSS 設計書"
---

最終更新: 2026-09-25（新規作成、#1655）

## 1. 概要

フォールダブル端末・広画面対応（[MorningStatusApp#1648](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1648)）を契機に導入した [Panda CSS](https://panda-css.com/) のセットアップ内容と、既存スタック（Tailwind CSS v4・CSS Modules・`app/globals.css`）との共存方式を扱う設計書（[MorningStatusApp#1655](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1655)）。

Panda CSS は Zero-Runtime（ビルド時にCSSを静的生成する）かつ TypeScript の型補完が効くスタイリングライブラリ。フォールダブル端末の展開判定（~580px付近）のようなカスタムブレークポイントを型安全に扱える点、および Next.js App Router との親和性を理由に採用した。

実際にコンポーネント・画面へ Panda CSS を適用していく段階移行の範囲は本書の対象外で、[MorningStatusApp#1656](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1656) 側で決定する。本書は、その前提となる「導入設定」と「既存スタックとの共存方式」の確定内容に限定する。長期的にはTailwind CSSを撤去しPanda CSS単独の構成へ移行する方針であり、その位置づけは§5を参照。

---

## 2. セットアップ内容

- 依存関係: `@pandacss/dev` を devDependency として追加
- 設定ファイル: リポジトリルートの `panda.config.ts`
  - `include`: `./app/**/*.{js,jsx,ts,tsx}` と `./components/**/*.{js,jsx,ts,tsx}`（Next.js App Router のディレクトリ構成に合わせる。`panda init` の初期値である `src/`・`pages/` はこのプロジェクトでは使わない）
  - `preflight: false`（§3-1参照）
  - `outdir: "styled-system"`（生成物。`.gitignore` に追加し、コミット対象外とする。`bunx panda codegen` または後述のPostCSSプラグインがビルド時に自動生成する）
- PostCSS統合: `postcss.config.mjs` の `plugins` に `@tailwindcss/postcss` と並べて `@pandacss/dev/postcss` を追加。`panda init --postcss` は初期状態で `postcss.config.cjs` を別ファイルとして生成するため、既存の `postcss.config.mjs` に統合し、重複するPostCSS設定ファイルを残さないこと
- `app/globals.css` の `@import "tailwindcss";` の直後に `@layer reset, base, tokens, recipes, utilities;` を追加。`@pandacss/dev/postcss` はビルド時にこの宣言の位置へ生成CSSを注入する

---

## 3. Tailwind CSS v4 との共存方式

### 3-1. カスケードレイヤーの優先順位

Tailwind CSS v4 は `@import "tailwindcss"` の展開により `@layer theme, base, components, utilities;` を、Panda CSS は `@layer reset, base, tokens, recipes, utilities;` をそれぞれ宣言する。CSSの `@layer` は同名レイヤーであれば宣言位置に関わらず1つに統合され、初出のレイヤー名だけがその位置に新規追加される仕様のため、実際のレイヤー優先順位（低→高）は次のようになる。

```
theme < base(Tailwind+Panda共有) < components < utilities(Tailwind+Panda共有) < reset < tokens < recipes
```

`base` と `utilities` は Tailwind・Panda 両方が同名レイヤーを使うため統合され、レイヤー内では**後から追加されたCSSほど優先される**（`globals.css` 内で Tailwind の `@import` より Panda の `@layer` 宣言が後にあるため、同一プロパティが競合した場合は Panda 側の指定が勝つ）。実機検証（Playwright、`class="bg-red-500"` と `css({ bg: "blue.500" })` を同一要素に適用）でも Panda側が優先されることを確認済み。

> **備考:** Panda の `preflight`（ブラウザデフォルトスタイルのリセット）は `false` に設定している。Tailwind v4 が `@import "tailwindcss"` により自前の preflight を `base` レイヤーへ既に注入しており、二重適用を避けるため。

### 3-2. レイヤー外（unlayered）CSSは常に最優先

`app/globals.css` の `:root` 変数定義や `*, html, body` 等、`@layer` で囲まれていないCSSは、CSS仕様上どの `@layer` 内のCSSよりも常に優先される。既存のグラスモーフィズム等のカスタムスタイルはこの位置にあり、Panda・Tailwindいずれのユーティリティクラスとも衝突しない。

### 3-3. `.container` → `.app-container` への改名と、Panda化を見送った経緯（重要な注意点）

> **備考（バグとして顕在化した問題と対策）:** 共通レイアウトの最大幅（1200px）を実現していた独自クラス `.container`（`app/globals.css`、`app/layout.tsx` 等）を Panda 化する過程で、2段階の技術的な非互換が技術検証中に判明した。
>
> **問題1（クラス名の衝突）**: `.container` という名前のまま Panda の `globalCss` に移行したところ、幅1920pxで通常画面のmax-widthが意図しない`1536px`になった。原因は、Tailwind CSS v4 が `@import "tailwindcss"` により、ソース内で `container` というクラス名トークンが使用されていると、組み込みの**レスポンシブ `.container` ユーティリティ**（`@layer utilities`、ブレークポイントごとに `max-width` が変わる）を自動生成するため。移行前は独自の `.container` が `@layer` の外（unlayered）にあり §3-2 の理由で常に最優先されていたため問題にならなかったが、Panda の `globalCss`（`base` レイヤー）に移した時点で、より優先度が高い `utilities` レイヤーにある Tailwind組み込み `.container` に負けるようになった。
>
> → 対策として、クラス名を `.app-container` に改名し、Tailwindの組み込み `.container` と名前の衝突を避けた（ソース上のトークン`container`が無くなることで、TailwindのJITスキャンが組み込みユーティリティを生成しなくなる効果もある）。
>
> **問題2（プロジェクト自身のレイヤー外リセットとの衝突。改名だけでは解決しない）**: `.app-container` に改名した後も、`padding`/`margin` が `0` になる不具合が残った。原因は、`app/globals.css` の `* { box-sizing: border-box; padding: 0; margin: 0; }` という、**このプロジェクト自身が持つレイヤー外のリセットCSS**。§3-2の通りレイヤー外CSSは常に最優先されるため、Panda の `globalCss`（レイヤー内）に置いた `.app-container` の `padding`/`margin` 指定は、詳細度に関わらずこのリセットに負ける。Tailwindとは無関係に、**「レイヤー外CSSを前提にした既存の `globals.css` の構造」と「Panda の globalCss（レイヤー内）」がそもそも噛み合わない**という、より根本的な非互換であることが分かった。
>
> **最終対応**: `.app-container` の**クラス名改名は維持**しつつ、**CSS定義自体はPandaの`globalCss`に移さず、従来通り`app/globals.css`へレイヤー外の生CSSとして書く**方針に変更した（§5「将来方針」も参照）。`globals.css` 側のレイヤー外リセット構造ごと見直す（全廃してPanda/Tailwindのレイヤー体系に揃える）選択肢も検討したが、影響が全画面に及ぶ大改修になるため本Issueの範囲外とした。

`.app-container` の実体は次の通り（`app/globals.css`。レイヤー外の生CSSとして維持）。

```css
/* Main Layout Grid */
.app-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 2rem;
}

/* 画面幅いっぱいに使う画面（最大幅の制限を外す。世代マトリックス画面） */
main.app-container:has(> [data-wide-canvas]) {
  max-width: none;
}

@media (max-width: 768px) {
  .app-container {
    padding: 0 1rem;
  }
}
```

ワイドキャンバス例外（世代マトリックス画面のみ最大幅を外す仕組み）の考え方自体は変更していない。[世代マトリックス 画面設計書](/design/member/generational-matrix-screen-design) §4-8を参照。`data-wide-canvas` 属性をページ直下に付与する実装（`app/generational-matrix/page.tsx`）も変更なし。

影響を受けた参照元（`className="container"` → `className="app-container"` に改名）: `app/layout.tsx`（header・main・footer）、`app/ameba/page.tsx`、`app/instagram/page.tsx`、`app/instagram/[accountId]/page.tsx`、`app/tiktok/page.tsx`、`app/tiktok/official/[accountId]/page.tsx`、`app/tiktok/og/[memberId]/page.tsx`、`app/youtube/page.tsx`、`app/youtube/official/page.tsx`、`app/youtube/og/[memberId]/page.tsx`。

---

## 4. カスタムブレークポイント（`fold`）

フォールダブル端末の展開時（~580px付近）を判定するため、`panda.config.ts` の `theme.extend.breakpoints` に `fold: "584px"` を追加した。Panda のブレークポイントは `min-width` ベース（モバイルファースト）で解釈されるため、[CLAUDE.mdのモバイルファースト規約](https://github.com/Tatsukiyoshi/MorningStatusApp/blob/main/CLAUDE.md)と自然に合致する。

```ts
theme: {
  extend: {
    breakpoints: {
      fold: "584px",
    },
  },
},
```

デフォルトのブレークポイント（`sm`・`md`・`lg`・`xl`・`2xl`）は `extend` により維持される。584pxという値は、Samsung Galaxy Fold系の展開時インナーディスプレイ幅を目安とした一般的な業界慣行値。

実際にこのブレークポイントを使う一覧画面（ライブ一覧・SNSアカウント一覧等）への適用は、[MorningStatusApp#1656](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1656) の対象。

---

## 5. 段階移行の方針と将来方針

本Issueでは、上記のセットアップと `.app-container`（ワイドキャンバス機構。§3-3の理由によりCSS定義自体は `globals.css` に残す）の対応のみを対象とする。それ以外のコンポーネント・画面をPanda化する範囲・優先順位は、本書で確立した共存方式をもとに [MorningStatusApp#1656](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1656) 側で決定する。

### 将来方針: Tailwind CSS の撤去とPanda CSS単独化

§3-3で判明した2つの非互換（Tailwind組み込みユーティリティとの命名衝突、`globals.css` のレイヤー外リセットとの構造的な非互換）は、いずれも「TailwindとPandaが同居し、かつ `globals.css` にレイヤー外CSSが残っている」という過渡的な状態に起因する。共存を維持し続けるコストを避けるため、Tailwind CSS v4 を撤去し、Panda CSS単独の構成へ移行する方針とする。Tailwindが無くなれば組み込みユーティリティとの命名衝突は原理的に発生しなくなり、`globals.css` のレイヤー外リセット（`:root` 変数・`* {...}` 等）もPandaの `globalCss`（またはPandaのpreflight）に置き換えれば、`.app-container` を含む共通レイアウトのCSSも安全にPanda化できるようになる。

この撤去（既存画面・コンポーネントで使われている全てのTailwindユーティリティクラスをPandaの書き方に置き換える作業。#1655時点の調査では対象は`app/`・`components/`配下223ファイル中25ファイル）は、[MorningStatusApp#1656](https://github.com/Tatsukiyoshi/MorningStatusApp/issues/1656) のフォールダブル対応と一体で実施する方針に変更した（当初は段階移行が十分に進んだ後の別Issueとする想定だったが、Tailwindとの共存コスト（§3-3）を踏まえ前倒しした）。

---

## 改訂履歴（バージョン降順に記載）

| 版 | 更新日 | 変更内容 |
| --- | --- | --- |
| 1.0 | 2026-09-25 | 新規作成（#1655） |
