迷わないReactスタイリング設計:Panda CSSが導く最適解(Part1)

ごあいさつ

レバレジーズ株式会社 アジャイルエフェクトチームの田代です。

我々アジャイルエフェクトチームは、スクラムにおける様々なプロセスを可視化し、生産性改善に繋げるためのSaaSプロダクト「Agile Effectを開発しています。
当プロダクトは、とあるPMの社員が社長に直接事業企画を提案したことがきっかけで誕生しました。昨年4月に事業が正式に立ち上がり、そこからわずか1年後の今年4月に正式リリースを迎えることができました。(レバレジーズは、アイデアを積極的に取り入れられる風土があり、意思決定の速さと挑戦を歓迎するカルチャーが色濃く根付いています!)

アジャイルエフェクトチームの特徴は「どのチームよりアジャイルを体現した組織」であることです。「スクラム改善のプロダクトを開発する上でアジャイルを体現し効率的にプロジェクトを進められるチームであることは大前提」というプライドの下、5名で事業をリードしています。
それぞれの得意分野や主な役割こそありますが、明確な役割分担はありません。日々の業務の中で、POが開発や設計に関わることもありますし、開発メンバーが企画・営業・マーケに関わることもあります。また、Agile Effectを活用することで全メンバーが主体となって改善サイクルを高速で回すことができています。

これにより高いアジリティを発揮し、
「定常的な週2〜3回ペースでのリリース」
「ユーザーから要望があった機能の1週間以内リリース」
などが実現できています。

我々がプロデュースする「Agile Effect」には、社内外でご利用いただいているスクラムチームの知見が詰め込まれており、今後も要望を取り入れながら、プロダクトを漸次的にアップデートし続けていきますので、ぜひ無料でご試用ください。
皆様のご利用をお待ちしております!

はじめに

早速ですが、エンジニアの皆様。

「フロントエンド開発」やっていますか?
「CSS」書いてますか?

当記事では、TypeScriptベースのスタイリングライブラリである「Panda CSS」のご紹介と、実運用で得た知見を共有いたします。
これらの問いに対して「YES」と回答した方であれば、学びに繋がる内容となっていますのでぜひご一読ください。

対象読者

  • アプリケーションのフロントエンド開発に携わるエンジニア
    • 特に、スタイリングに関する内部品質で悩んでいる方
  • Reactで新しくアプリケーションを作ろうとしている方
  • Panda CSSの実運用事例について詳しく知りたい方

記事を通して得られること

  • TypeScriptベースのCSSライブラリ「Panda CSS」について
  • 他のスタイリング手法(CSS Modules/SCSS/Tailwindなど)とPanda CSSの比較
  • 型安全なCSSやデザインシステム構築に役立つPanda CSSの基本知識
  • 実際のプロダクトで運用する際に生じる課題と対処方法
  • Panda CSSを使った際の開発効率向上や保守性アップの具体的なイメージ

以上の内容をカバーすることで、読者の皆様がPanda CSSの導入メリットを把握し、プロダクトのスタイリング設計をより快適に進められるようになることを目指しています。今後のフロントエンド開発に、少しでもお役に立てれば幸いです。

どう幸せになったのか

まず結論をお伝えすると、Panda CSSを採用したことで以下のような改善が実現し、開発体験が劇的に向上しました:

  • 型安全なCSS:TypeScriptによるスタイリングで開発速度と保守性が向上。
  • 宣言的かつ画一的なスタイリング:動的な値に基づくスタイリングが宣言的かつ1箇所に集約され、保守性/可読性が向上。
  • DOMとスタイリングの責務分離:「Typography」「Flex」など、スタイリング用のコンポーネントがDOMに影響してしまう悩みからの解放。
  • デザインシステムの踏襲:デザイントークンを型レベルで組み込み、デザインとの乖離を排除。

ご存じのとおり、Reactのスタイリングには「Sass/SCSS」「CSS Modules」「Styled Components」「Tailwind CSS」「Emotion」「StyleX」など様々な選択肢があります。それぞれ一長一短があるため、どれを採用するのか悩ましいところですが、今回紹介するPanda CSSは、これらの手段の“いいとこ取り”を叶えてくれる存在だと感じています。

実運用を通じても開発体験の良さを実感しており、個人的にはPanda CSSが「Reactのスタイリング手法における最適解」だと思っています。 ここで挙げた以外にもPanda CSSを使うことで得られる恩恵は様々であり、記事全体を通してご紹介出来ればと思います。

目次

※記事全体で分量が多くなってしまったため、記事を3つに分けて順次公開していきます。
今回はPart1となります。

  • Part1:Panda CSSとの出会いとその魅力
    • 導入背景
    • Panda CSSの特徴と、他のスタイリング手法との比較
    • Panda CSSを使った基本のスタイリング
  • Part2:実践!Panda CSSの使い方(Coming soon)
  • Part3:Panda CSSの課題と未来への展望(Coming soon)

Part1では、Panda CSSの採用に至った背景とその魅力についてお話しします。
後日公開するPart2/Part3では、実際にどのようにプロダクトで運用しているかを、設計事例とともに紹介する予定です。

導入背景

「Agile Effect」では、Reactを用いてフロントエンドを開発しています。
立ち上げから約1年間はCSS Modulesを使っていましたが、次第に以下のような課題が出てきました:

  • 静的型付けが効かない
    • 単純に開発体験の悪さを感じ、エラー発生やコミュニケーション面など、将来的な開発スピードへの影響が懸念されました。
  • デザインシステムの作成開始
    • デザイン自体がまだプロトタイプの状態でしたが、本格的なデザインシステム制作がスタート。スタイリング設計を見直す大きな要因に。
  • 汎用スタイルコンポーネントの責務拡大
    • 「Typography」「Flex」など、スタイル適用のためのコンポーネントが肥大化し、SRP原則から逸脱しはじめていました。
  • デザイントークンの取扱い
    • 基本的なスタイリングはCSS Modulesで行いましたが、デザイントークンに限ってはTypescriptの定数を経由し、Inline Styleで管理していました。この影響で、スタイルの記述が.module.cssと.tsxの双方に散在していました。

これらを踏まえ、スタイリング設計をゼロから見直すことに。
調査と比較検討の末、我々が採用したのが Panda CSS でした。

Panda CSSの特徴と、他のスタイリング手法との比較

CSSは、TypeScriptベースの“ゼロランタイム”CSS-in-JSライブラリです(セットアップなどの基本知識はここでは割愛します)。公式ドキュメントの「なぜPandaを選ぶのか?」にあるとおり、主に以下のような特徴が挙げられます。

  • 静的解析
    • ビルド時にスタイルを解析・分析し、フレームワークに依存しない純粋なCSSファイルを出力します。
  • PostCSS
    • 静的解析の後、PandaはPostCSSプラグインのセットを使用して、ビルド時に解析されたデータをアトミックCSSに変換します。これにより、PandaはPostCSSをサポートする任意のフレームワークと互換性があります。
  • Codegen
    • ブラウザ実行時にスタイルを注入せず、ビルド時に軽量なランタイムJSコードを生成。結果としてランタイム負荷が低くなります。
  • 型安全性
    • Pandaは、cssプロパティとデザイントークンの型安全性を提供するために、csstypeと自動生成された型付けを組み合わせます。
  • パフォーマンス
    • 必要なアトミックCSSのみを最適化して出力。不要なCSSが入らずバンドルサイズが抑えられます。
  • 開発者エクスペリエンス
    • Pandaは、レシピ、パターン、デザイントークン、JSXスタイルプロップなどの豊富な機能により、優れた開発者体験を提供します。
  • モダンCSS
    • カスケードレイヤー、CSS変数、:where/:is等、最新のCSS仕様に対応。


また、私なりに他のスタイリング手法とのおおまかな比較表も作成してみました。

項目 静的型解析 実行タイミング パフォーマンス 型安全DesignTokenサポート 動的スタイリング
Sass/SCSS
(Pure CSS)
× ビルド時 ⚪︎
(肥大化しやすい)
×
(JSが必要)
CSS Modules
(型生成を支援するライブラリ使用で一部可)
ビルド時 ⚪︎
(肥大化しやすい)
×
(JSが必要)
Styled Components / Emotion
(プロパティレベルの解析不可)
ランタイム時 ×
(型レベルの厳密性は薄い)
Tailwind CSS
(プロパティレベルの解析不可)
ビルド時
(型レベルの厳密性は薄い)
⚪︎
Panda CSS ビルド時 ⚪︎


表から分かる通り、Panda CSSにはこれといった大きなデメリットが見当たらず、静的解析や型安全性、ゼロランタイムなどの特色はどれも非常に魅力的でした。
もちろんプロジェクトとの相性等はあるかと思いますが、我々の場合は移行負荷も低く大きな懸念が無かったため、全面的にPanda CSSへ移行することにしました。

Panda CSSを使った基本のスタイリング

ここからは、Panda CSSにおけるスタイリングの一連の流れを見ていきます。
公式ドキュメントにあるように、Panda CSSは「TypeScriptベースのコード定義をビルド時に解析し、最終的に純粋なCSSファイルを出力する」フローが大きな特徴です。

ポイント:
Panda CSSでは、最新のカスケードレイヤーが活用されているのも大きな特徴の一つです。

CSSレイヤーを活用することで、複数のレイヤーにまたがるスタイルの優先順位が明確化され、アトミックCSSやデザイントークンとの相性がより良くなっています。詳しくは、公式ドキュメントのカスケードレイヤーのページをご確認ください。この仕組みを前提に、次章からはPanda CSSでどのようにスタイルを定義し、ビルドしているのかをご紹介していきます。

基本のスタイリング構文

Panda CSSのスタイリングは、styled-system/css が提供する css() や cva() などの関数を用いて定義します。まずはもっともシンプルなcss()を使った例を見てみましょう。
こちらが最も基本的な定義の例です。

import { css } from '../styled-system/css'
 
const styles = css({
  backgroundColor: 'gainsboro',
  borderRadius: '9999px',
  fontSize: '13px',
  padding: '10px 15px'
})
 
// 生成されるクラス名:
// --> bg_gainsboro rounded_9999px fs_13px p_10px_15px
 
<div className={styles}>
  <p>Hello World</p>
</div>

この定義を基にビルドした結果、CSS出力は次のようになります。

@layer utilities {
  .bg_gainsboro {
    background-color: gainsboro;
  }
 
  .rounded_9999px {
    border-radius: 9999px;
  }
 
  .fs_13px {
    font-size: 13px;
  }
 
  .p_10px_15px {
    padding: 10px 15px;
  }
}

上記のように、TypeScriptのオブジェクト構文でCSSプロパティを記述するだけでOKです(プロパティ名や値は型安全性が効きます)。実行時ではなくビルド時にCSSに変換され、ブラウザに読み込まれるころには純粋なCSSファイルとして提供されます。

ポイント:
css()以外にも、バリエーションを定義するためのcva()や、汎用レイアウトなどをRecipeとしてまとめるdefineRecipe()など、複数のアプローチがあります。
どれも「TypeScriptでCSSを記述する → ビルド時に最適化されたCSSが生成される」という点は共通です。(参考)

スタイル生成の流れ

Panda CSSを利用すると、TypeScriptで記述したスタイルがビルド時に最適化され、最終的には純粋なCSSファイルとして出力されます。ここでは、その一連の流れを順に確認していきます。

1.「型付きのスタイル定義」を記述する

まず、開発者が行うのはTypeScriptによるスタイル定義です。css()cva() に渡すオブジェクトや変数には型安全性が適用されるため、プロパティ名や値の誤りが早期に検知できます。

2.ビルド時に「原子化」と「不要なものの排除」

ビルドプロセスでは、Panda CSSがソースコードを走査し、同じプロパティや重複する宣言をまとめてAtomic CSSへ変換します。
Atomic CSS: CSSプロパティ単位でクラスを生成する考え方です(例: .p_8px_16px, .rounded_4px など)。
使われていないクラスは自動的に削除され、必要最小限のCSSだけがビルド成果物として残ります。

3.純粋なCSSファイルとしてブラウザへ

最終的な変換結果は、特定のJSライブラリに依存しない純粋なCSSファイルとして出力されます。つまり、ランタイムでスタイルを注入する必要はありません。ページ読み込み時には、既に最適化されたCSSが供給されているため、“ゼロランタイム”を実現できます。

ポイント
・型安全にCSSが書ける
・バンドルサイズが肥大化しにくい
・実行時のオーバーヘッドが少ない
・クラス名の競合を最小限に抑えられる

このように、型安全性と最適化済みのCSS出力を同時に得られるところが、Panda CSSの大きな特長です。

まとめ

Panda CSSで「書きやすさ」と「最適化」を両立

書きやすさ
TypeScriptでのオブジェクト記述なので、補完や型チェックが効き、スタイル記述のミスを減らせます。

最適化
ビルド時にスタイルを集約・最適化して出力するため、ランタイムで注入する仕組みよりもパフォーマンス面のメリットがあります。

Part2以降では、これらの基盤を活かしてデザインシステムをどのように型安全に落とし込んでいくか、さらに踏み込んだ使い方を紹介します。

今回紹介した「基本のスタイリング」の部分だけでも十分恩恵がありますが、Panda CSSには、Design TokenやRecipe機能など、より高度なスタイリングパターンをサポートする仕組みが豊富に用意されています。 これらを組み合わせることで「デザインシステムと型安全性の融合」を実現し、プロダクト全体のスタイリングを一貫性のあるものへと導いてくれます。

次章ではさらに踏み込んで、Panda CSSが提供する「Recipe(CVA)」や」Config Recipe」を活用した共通スタイルの定義や、デザイントークンを組み込んだデザインシステム構築など、より実践的な活用事例を紹介していきます。
加えて、テスト環境やStorybookでスタイルが反映されない際のトラブルシューティングなど、リアルな運用Tipsについても触れますので、ぜひご期待ください。

ご一読いただき、ありがとうございました!