この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは、CX事業本部MAD事業部の森茂です。
まだReleaseバージョンも付与されていないため開発中とも思われますが、Microsoft製のCSS-in-JSライブラリGriffelがGitHubに公開されてたのでさっそく試してみました。
Griffelは正式なリリース版ではないため不確かな部分がございます。またアップデートなどで仕様が変更になる場合もございます。あらかじめご了承ください。
Griffel
まだライブラリの紹介ページなどはなくGitHubのドキュメントに紹介されている範囲ですが、特徴として下記4点を謳っているようです。(まだプロダクトアイコンもなさそう)
- Zero config start: Griffel has both runtime & build time implementations
- Optional build time transforms to improve performance
- Type-safe styles via csstype
- Uses Atomic CSS to reuse styles and avoid specificity issues with CSS
設定不要で、ランタイムだけでなくビルド時にもコンパイルすることで高いパフォーマンスを発揮することができる模様。もちろんcsstype
を利用しているため型補完を効かせた記述も可能なようです。
やってみた
今回は手っ取り早くNext.jsのプロジェクトを立ち上げて実装をしてみました。TypeScript用のテンプレートにつづけて@griffel/react
もインストールしておきます。
$ yarn create next-app griffel-example --typescript
$ yarn add @griffel/react
Griffelはライブラリをインストールすればあとは利用するコンポーネントでimport
するのみというシンプル設計のようです。
makeStyles
スタイルの生成にはmakeStyles
を利用します。あらかじめ用意されているpages/index.tsx
を下記のように編集します。
pages/index.tsx
import type { NextPage } from 'next';
import { makeStyles, mergeClasses } from '@griffel/react';
// スタイルを生成
const blue = 'blue';
const useClasses = makeStyles({
red: {
color: 'red',
fontSize: '3rem',
},
blue: {
color: blue,
},
});
const Home: NextPage = () => {
// classesオブジェクトに生成したスタイルを格納
const classes = useClasses();
return (
<div>
<h1 className={classes.red}>Welcome to Next.js!</h1>
<h1 className={(classes.red, classes.blue)}>Welcome to Next.js!</h1>
<h1 className={mergeClasses(classes.red, classes.blue)}>
Welcome to Next.js!
</h1>
</div>
);
};
export default Home;
MaterialUIと同じようにmakeStyles
という関数を利用してオブジェクト形式でスタイルを記述し、コンポーネント内でconst classes = useClasses()
のように実行してclasses.class名
という形でスタイルを利用します。
試してみたところクラス名を2つ以上当てた場合(className={(classes.red, classes.blue)}
)は、後ろのクラスにすべての情報が上書きされるようです。また、mergeClasses()
を利用すると同じプロパティがある場合は後ろのもので上書き、差分はすべて反映される仕組みになっています。
makeStaticStyles
makeStyle
とは別にmakeStaticStyles
というオブジェクトの代わりに文字列や配列を渡すことができる関数があります。makeStaticStyles
を利用するとbodyなどタグ自体にグローバルなスタイルを付与できます。文字列として渡すことができるため既存のCSSなどをそのまま渡すことが可能です。
pages/static.tsx
import type { NextPage } from 'next';
import { makeStaticStyles } from '@griffel/react';
const red = 'red';
// 文字列としてスタイルを渡すため通常のCSSでの記載と同じように書ける
const useStaticStyles1 = makeStaticStyles(`
body { background: ${red}; }
.foo { color: green; }
`);
const Home: NextPage = () => {
useStaticStyles1();
return (
<div>
<h1 className="foo">
Welcome to Next.js!
</h1>
</div>
);
};
export default Home;
bodyタグにはそのままスタイルが、h1タグには.foo
のスタイルが反映されています。
さいごに
最初はmakeStylesという命名からMaterialUIでのスタイリングを想像したのですが、文字列も扱えるためどちらかというとemotionのcss propを利用したスタイリング方法に近いと感じました。パフォーマンスについては使い込んでみないとわからないところがありますが、ゼロコンフィグでコンポーネント単位でも導入できるため使い勝手がよさそうです。
まだ開発中ながらあらたにCSS-in-JSの選択肢がひとつ増えたということになるかもしれません。以前からMeta(Facebook)製のCSS-in-JS(Stylex)も出ると言われているのでCSS-in-JS界隈はこれからもまだまだ悩ましい時代が続きそうな予感がしますね:)