PanndaCSSを使いこなそう
Panda CSS とは
Panda CSS とは Chakra UI の開発チームが開発した
新しい CSS in JS のライブラリで
公式ドキュメントに記載してある通り
サーバーファースト時代における CSS-in-JS の課題を解決することを目的とした新しい CSS-in-JS
です。
Chakra UI や Tailwind CSS など様々なライブラリから影響されており
それらのいいとこ取りをしたようなライブラリです。
インストール
さっそく使えるようにインストールしましょう。
ドキュメントに沿ってインストールしていきます。
// npmの場合
npm install -D @pandacss/dev
// yarnの場合
yarn add -D @pandacss/dev
// pnpmの場合
pnpm install -D @pandacss/dev
次にpanda init
を行って設定ファイルを作成します。
// npmの場合
npx panda init --postcss
// yarnの場合
yarn panda init --postcss
// pnpmの場合
pnpm panda init --postcss
package.json を更新します。
"scripts": {
+ "prepare": "panda codegen",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"prepare": "panda codegen"を追加することにより
新しくパッケージを追加した際に
自動的にstyled-stystem
フォルダに
各ファイル設定が作成されます。
次にsrc/app
フォルダにあるglobal.css
を開いて
全て消してから次のコードを入力します。
@layer reset, base, tokens, recipes, utilities;
これで pandaCSS を使えるようになりました。
基本的な使い方
基本的な Panda CSS での書き方です。
className の後にcss({})
とすることで
css を記述することができます。
import { css } from "../styled-system/css";
<div
className={css({
backgroundColor: "red",
borderRadius: "9999px",
fontSize: "13px",
padding: "10px 15px",
})}
>
Panda!
</div>;
プロパティの簡略化
Panda CSS ではプロパティを簡略化できるものがあります。
先ほどの CSS を簡略化してみましょう。
import { css } from '../styled-system/css'
<div
className={css({
- backgroundColor: "red",
+ bg: "red",
- borderRadius: "9999px",
+ rounded:"9999px",
fontSize: "13px",
- padding: "10px 15px",
+ p: "10px 15px",
})}
>
Panda!
</div>
この様に一定のプロパティは簡略化することができ
コードを簡潔することができます。
入れ子のスタイル
子要素に同じプロパティを当てたい場合などに使用されます。
例えばリスト内の要素を同じプロパティを当てたい場合などに使用できます。
import { css } from "../styled-system/css";
<ul className={css({ bg: "red", "& li": { bg: "blue" } })}>
<li>P</li>
<li>a</li>
<li>n</li>
<li>D</li>
<li>a</li>
<li>!</li>
</ul>;
これにより ul の中の li 要素の全てに一定のスタイルを
適用させることができます。
疑似要素
:hover,:focus,::before などの疑似要素なども
_hover,_focus,_before
と記述することにより
簡単に設定することができます。
import { css } from "../styled-system/css";
<div
className={css({
bg: "red",
_hover: { bg: "blue" },
_focus: { bg: "green" },
})}
>
Panda!
</div>;
レスポンシブ
プロパティの簡潔化
Panda CSS ではレスポンシブの条件を直接適用することができます。
プロパティにブレイクポイントとスタイルを入力することで
記述が簡潔になります。
import { css } from "../styled-system/css"
<span
className={css({
- fontWeight: "medium",
- lg: { fontWeight: "bold" }
+ fontWeight: { base: "medium", lg: "bold" }
})}
>
Text
</span>
一行のほうがパッと見てわかりやすいですね。
ブレイクポイントの設定
ブレイクポイントのデフォルトではこの用に設定されています。
const breakpoints = {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
};
ブレイクポイントは panda.config.ts にて
このように変更することができます。
export default defineConfig({
preflight: true,
include: ["./src/**/*.{js,jsx,ts,tsx}"],
exclude: [],
outdir: "styled-system",
theme: {
extend: {
+ breakpoints: {
+ sm: "640px",
+ md: "768px",
+ lg: "1024px",
+ xl: "1280px",
+ "2xl": "1536px",
+ },
},
},
});
ブレイクポイントの指定
例えばメニューやロゴなど,
タブレットとパソコンの画面では表示させたくないなー
みたいな場合もあると思います。
その場合To
を用いることで作成することができます。
コードの例と一緒に見てみましょう。
import Link from "next/link";
import { css } from "../styled-system/css";
function App() {
return (
<nav className={css({ display: { mdToXl: "none" } })}>
<ul>
<li>
<Link href="/">home</Link>
<Link href="/about">about</Link>
</li>
</ul>
</nav>
);
}
mdToXl
は display:none を指定しているので
nav が 768px〜1280px の間は表示されない様になります。
パターン
Panda CSS には様々なレイアウトパターンがあり、
必要に応じてプロパティを指定することにより
使用することができます。
全てではないですが、少し紹介します。
Container
Container パターンを指定することで
デフォルトで次の CSS が設定されます。
・maxWidth: 8xl
・marginX: auto
・position: relative
・paddingX: { base: 4, md: 6, lg: 8}
import { container } from "../styled-system/patterns";
function App() {
return (
//通常クラスの中はcssだがcontainerを指定することで使用可能になる。
<div className={container()}>
<div>First</div>
<div>Second</div>
<div>Third</div>
</div>
);
}
Flex
Flex パターンは使用することでデフォルトで flex が適用され
さらにいくつかのショートカットを使用することができるようになります。
・align: align-items のショートカット
・basis: flex-basis のショートカット
・direction: flex-direction のショートカット
・grow: flex-grow のショートカット
・justify: justify-content のショートカット
・shrink: flex-shrink のショートカット
・wrap: flex-wrap のショートカット
import { flex } from "../styled-system/patterns";
function App() {
return (
<div
className={flex({
align: "center",
direction: "column-reverse",
justify: "center",
})}
>
<div>First</div>
<div>Second</div>
<div>Third</div>
</div>
);
}
Circle
Circle パターンはその名の通り
丸を作成する為に使用されます。
size プロパティを使用することができるようになります。
・size: 丸の大きさを指定することができます。
import { circle } from "../styled-system/patterns";
function App() {
return (
<div className={circle({ size: "10", overflow: "hidden" })}>
<img src="" alt="" />
</div>
);
}
他にも色んな便利のパターンがありますので,
よかったらドキュメントをご覧ください。
レシピ
ボタン、メニュー、タイトルなど繰り返し使いたい要素また
その要素に似たスタイルを作りたい場合などに重宝します。
今回は色と、サイズが違うボタンのレシピを作成してみます。
import { cva } from '../styled-system/css';
export const button = cva({
base: {
display: "flex",
},
variants: {
color: {
cream: { bg: "#FFE4DB", color: "#DF4D20" },
orange: { bg: "#DF4D20", color: "#ffffff" },
},
size: {
lg: { fontSize: "24px", padding: "8" },
sm: { fontSize: "12px", padding: "4" },
},
},
});
色がクリーム色、オレンジ色、サイズが lg、sm のレシピを作成しました。
cva
はレシピをコンポーネントに適用するために必要な関数です。
これを実際に使ってみましょう。
import { button } from "./button.css";
const Button = () => {
return (
<button className={button({ color: "orange", size: "sm" })}>送信</button>
<button className={button({ color: "cream", size: "lg" })}>送信</button>
)
}
これで別パターンのボタンを作成することができました!
便利ですね。
style-props
style-props を使用すると JSX のプロパティとして
UI を作成することができます。
使用方法はまずpanda.config.ts
ファイル内に
jsxFramework: 'react'
と入力します。
import { defineConfig } from "@pandacss/dev";
export default defineConfig({
// ...
jsxFramework: "react",
});
JSX ランタイムを作成するためにcodegen
を実行します。
// npmの場合
npx panda codegen --clean
// yarnの場合
yarn panda codegen --clean
//pnpmの場合
pnpm panda codegen --clean
これで JSX のプロパティで
作成することができるようになります。
先程の パターン flex と同じコードで見てみましょう。
import { styled } from "../styled-system/jsx";
function App() {
return (
<styled.div
display="flex"
alignItems="center"
justifyContent="center"
flexDirection="column-reverse"
>
<div>First</div>
<div>second</div>
<div>Third</div>
</styled.div>
);
}
このようにプロパティを props で指定することができます。
まとめ
実際触ってみて、色やブレイクポイント,感覚などが
TailwindCSS に似ていてとても使いやすかったです。
さすが色んなプラグインのいいとこ取りしてるだけ
あるなーと感じました。
これから新しいプロジェクトで Panda CSS が使われる機会が
多くなるかもですね!
他にも色んな便利な機能があるので
ドキュメントを読みながら知見を深めていきたいと思います。
Discussion