🐼

話題のゼロランタイムなCSS-in-JSライブラリ「Panda CSS」をNext.jsに導入してみた

2023/07/06に公開
2

Panda CSSとは

はじめに、今回のメインテーマとなるPanda CSSについて簡単に紹介します。

https://panda-css.com/

CSS-in-JS with build time generated styles, RSC compatible, multi-variant support, and best-in-class developer experience

Panda CSSとは、上記公式サイト冒頭にもあるようにパフォーマンス面の課題をクリアしつつ、最高クラスの開発体験も両立したCSS in JSライブラリとなっています。

(最近ではNext.jsのReact Server Componentsが安定版になったこともあり)従来のようにランタイムCSS in JSを利用することが推奨されなくなってきている中、Chakra UIと同じ開発元によって、ゼロインタイムを実現したPanda CSSが新たにリリースされました。

多くのJavaScriptフレームワークに対応しており、Next.js 13のApp Routerはもちろん、旧来のPages Routerにも対応しています。手軽に導入できるため、さっそく次の章からセットアップしていきます。

まずはNext.jsアプリケーションをセットアップしよう

今回は、npm経由でNext.js(App Router)を導入するところから始めます。

下記コマンドを実行して、Next.jsアプリケーションをインストールしましょう。諸々質問を聞かれますが、今回はTailwind CSSを導入するかどうかの質問以外はYesと答えました。

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

Next.jsアプリケーションにPanda CSSを導入しよう

新たに作成したディレクトリに移動し、下記コマンドを実行します。

npm install -D @pandacss/dev

続けて下記コマンドを実行することで、postcssの設定に関するファイルが自動で作成されます。

npx panda init --postcss

次に、package.jsonに下記記述を追記します。今後はnpm installの実行時に、panda codegenが実行されることで、styled-systemに各設定ファイルが自動で作成されるようになります。

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

また、自動で生成されたstyled-systemはGitで管理する必要がないため、.gitgnoreに下記記述を追加しておきましょう。

.gitignore
+ styled-system

次に、globals.cssの全ての記述を削除し、下記記述を追加します。

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

次に、page.tsxの全ての記述も削除し、下記記述を追加します。

src/app/page.tsx
+ import { css } from "../../styled-system/css";
+
+ export default function Home() {
+   return (
+     <div
+       className={css({
+         fontSize: "2xl",
+         fontWeight: "bold",
+         margin: "30px",
+       })}
+     >
+       Hello 🐼!
+     </div>
+   );
+ }

最後に、下記コマンドを実行し、開発サーバーを起動します。

npm run dev

そうすると、http://localhost:3000で下記の画面が表示されるはずです。Panda CSSによるCSSの設定が有効になっていることが確認できますね。

読み込まれているCSSの内容を確認すると、同じ内容のCSSが重複しないように必要なCSSだけビルドされ、それらが記載されたCSSファイルを読み込む形になっているようです。仕様に関してはTailwind CSSから良い影響を受けているように思えますね。

※Next.jsにおけるPanda CSSのセットアップ方法は以下公式docを参考にしました。
https://panda-css.com/docs/getting-started/nextjs

開発体験が良すぎる件について

Visual Studio Codeを使っていると、各CSSプロパティの予測補完が効きます。Chakra UIと同様、CSSの開発体験はとても良いです。サクサク実装を進めることができます。

Tailwind CSSでも補完が効くようなVisual Studio Codeの拡張機能は用意されておりますが、あくまでTailwindCSSで用意されているクラス名の予測補完となるため、クラス名を覚える作業がある程度必要となります。ただ、Panda CSSではそれすら必要なく、CSSファイル内でCSSを実装する時と近い感覚で実装を進められるのが好きです。

それなら普通にCSS Modulesを使えばええやん」という言葉が飛んできそうですが、CSS設計を考える必要がなく、クラスの命名から実装に時間を取られずに各要素に直接CSSを実装できるのは、とても楽です。

さらに、型安全なので、TypeScriptである恩恵を十分に受けられます。Chakra UIでも同様の開発体験を得られますが、先ほど紹介したようにPanda CSSはゼロランタイムです。ビルド時にCSSが生成されることで、パフォーマンス面で強みを発揮します。もはや上位互換なのです。

breakpoint(ブレークポイント)の設定について

ブレークポイントの設定についてもラクラクです。下記のような記述を追加するだけで、今回であれば@media screen and (min-width: 768px)で有効にするCSSを実装できます。

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

export default function Home() {
  return (
    <div
      className={css({
        fontSize: "2xl",
        fontWeight: "bold",
        margin: "30px",
+       md: {
+         fontSize: "3xl",
+         margin: "50px",
+       },
      })}
    >
      Hello 🐼!
    </div>
  );
}

ブレークポイントの数値設定はpanda.config.tsで以下のようにカスタマイズできます。

panda.config.ts
theme: {
  extend: {
+   breakpoints: {
+     sm: '640px',
+     md: '768px',
+     lg: '1024px',
+     xl: '1280px',
+     '2xl': '1536px'
    }
  }
},

他にも、ブレークポイントの設定を範囲をターゲットにしたり、各CSSプロパティごとに記述できたりと自由度も高いことが伺えます。詳細は以下公式docを確認してみてください。

https://panda-css.com/docs/concepts/responsive-design

他にも便利な機能が豊富な件について

他にも:hover:focusなどの条件付きスタイルや、疑似要素のスタイルもブレークポイントの設定と同じような形式で実装できます。また、Chakra UIの良い部分を引き継いだ設計となっており、global CSSや各パターン、トークンの設定も可能です。

そしてもちろん、Storybookにも対応しています。また、Chakra UI同様、Figmaとの連携も将来的には強くなりそうでワクワクします。今後はランタイムCSS in JSのリプレイスCSSライブラリとして、上位候補となりそうです。

Panda CSSを使う上での注意

iOS15.4未満には未対応

Panda CSSは@layerの技術を使ってCSSの優先順位を制御しています。

つまり、@layerに対応していないブラウザバージョンは、本ライブラリも対応していないということです。詳細については、上記のリンクをご確認ください。iOS Safariのバージョン15.4未満には対応していないことが、利用する上での判断基準となるでしょう。

各数値の設定は単位が必要になる

ReactやChakra UIを利用したときなど、いくつかのCSSプロパティが自動的に「px」に変換されることがあったと思われます。一方、Panda CSSでは、数値の値を自動変換しないため、明示的に単位を指定する必要があります。これにより、値が生のCSS値であることが明確になるため、むしろ可読性は上がりそうです。

今回の記事は以上になります。

ここまで読んでいただき、ありがとうございます🙏

LCL Engineers

Discussion

おとのおとの

【数日利用してみた所感を追記】

  • panda.config.tsにブレイクポイント以外のメディアクエリを追加する方法が不明?