この記事はコネヒトアドベントカレンダー2024の20日目の記事です。
styled-componentsで書かれたプロジェクトをあまり移行コストをかけずにゼロランタイムCSS in JSに置き換えられないか、といくつかのゼロランタイムCSS in JSを軽く味見してみました。
なぜゼロランタイムCSS in JSにするのかということについてはいろいろなところで語られているかと思いますのでここでは省略させていだただきます。
選定条件
条件としては以下の2点で選定しました。
- styled-componentsの書き方に近い
- ゼロランタイムCSS in JSである
選定した結果以下の3つを味見しました。
- Linaria : Linaria – zero-runtime CSS in JS library
- panda : https://panda-css.com/
- Kuma UI : https://www.kuma-ui.com/
味見
環境
Remix, Vite, npm
styled-components
まずstyled-componentの場合の実装例です。
import { styled } from 'styled-components'; const SubTitle = styled.h2` font-weight: bold; color: ${(props) => props.color || 'black'}; `; export default function Content() { return ( <div> <h1>Hello, World!</h1> <SubTitle color="red">red</SubTitle> <SubTitle color="blue">blue</SubTitle> </div> ); }
サンプルコードはこちらのリポジトリのPullRequestにも載せてあります。 Pull requests · yanamura/zero-runtime-css-in-js-sample · GitHub
Linaria
setup
npm install @linaria/core @linaria/react @wyw-in-js/babel-preset npm i -D @wyw-in-js/vite
// vite.config.ts import { defineConfig } from 'vite'; import wyw from '@wyw-in-js/vite'; export default defineConfig(() => ({ // ... plugins: [wyw()], }));
実装
import { styled } from '@linaria/react'; const SubTitle = styled.h2` font-weight: bold; color: ${(props) => props.color || 'black'}; `; export default function Content() { return ( <div> <h1>Hello, World!</h1> <SubTitle color="red">red</SubTitle> <SubTitle color="blue">blue</SubTitle> </div> ); }
感想
styled-compontntsと全く同じコードで実装できたので、移植は楽そうかもしれません。
気になるところをあげるとすると、ドキュメントがGitHubのdocs以下しかなさそうなところと、babelに依存しているところくらいでしょうか。
panda
setup
npm install -D @pandacss/dev npx panda init --postcss
// package.json
{
"scripts": {
+ "prepare": "panda codegen",
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
}
}
// panda.config.ts import { defineConfig } from "@pandacss/dev"; export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ["./src/**/*.{js,jsx,ts,tsx}", "./pages/**/*.{js,jsx,ts,tsx}"], // Files to exclude exclude: [], // Useful for theme customization theme: { extend: {}, }, syntax: 'template-literal', jsxFramework: 'react', // The output directory for your css system outdir: "styled-system", });
npx panda codegen --clean
ポイントとしてはstyled-components系のスタイル(JSX style)を使うには、panda.config.tsに jsxFramework: 'react' を追加して, npx panda codegen --clean する必要があるところです。
実装
import { styled } from '../styled-system/jsx'; const SubTitle = styled.h2` font-weight: bold; ` // color: ${(props) => props.color}; // 自前で定義したプロパティは使えない export default function Content() { return ( <div> <h1>Hello, World!</h1> <SubTitle>red</SubTitle> <SubTitle>blue</SubTitle> </div> ); }
感想
pandaは導入がややこしいです。ただ最初だけなのでそこまで気にする必要はないかもしれませんが。 prepareでpanda codegenが動いてstyled-systemフォルダ以下にファイルを生成しているのがちょっと気になりました。(ビルドしないとstyled-system以下を参照してもエディタ上ではエラーがでるのと、JSXを有効するときにこれを一回cleanしないといけなかったりと) 実装上は、styled-componentsのようにpropsを渡すことができないようなので、そういうコードを移植したい場合はちょっと困るかもしれません。
Kuma UI
setup
npm install @kuma-ui/core npm install -D @kuma-ui/vite
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import KumaUI from "@kuma-ui/vite";
export default defineConfig({
plugins: [
react(),
KumaUI({
// Enable WebAssembly support for Kuma UI. Default is false and will use Babel to transpile the code.
wasm: true // Optional
}),
],
});
実装
import { styled } from "@kuma-ui/core"; const SubTitle = styled.h2` font-weight: bold; `; // color: ${(props) => props.color}; // 自前で定義したプロパティは使えない export default function Content() { return ( <div> <h1>Hello, World!</h1> <SubTitle color="red">red</SubTitle>{/** colorはKumaUIのUtility Props(https://www.kuma-ui.com/docs/Components/UtilityProps#color) */} <SubTitle color="blue">blue</SubTitle> </div> ); }
感想
導入は一番楽でした! 実装上は、panda同様styled-componentsのようにpropsを渡すことができないようでした。 ただいくつかUtility Propsというのが用意されていてそれで代用できるケースもあるかもしれません。
総括
styled-componentの書き方を変えずにゼロランタイムCSS in JSにするには、Linariaがあまり既存のコードに影響が少なく持ってこれるという点ではよいかなという印象でした。
ただ、調べているうちに、Compiledではstyledの記法がdeprecatedになっていたりと、styled-componentsの書き方に縛られるのはあまりよくないのでは・・という感想を持ちました。 個人的にもstyled-componentsの書き方はパッと見で機能を持つコンポーネントなのかただ装飾だけのコンポーネントなのかわかりづらいのがあまり好きではないので、最初から採用するのであればstyledのスタイルよりはcssのスタイルのほうを選んだほうがよいかなと思っています。