Microsoft製CSS-in-JSライブラリGriffelを試してみた

ゼロコンフィグでシンプルなMicrosoft製CSS-in-JSライブラリGriffelをNext.jsで試してみました。
2022.02.14

この記事は公開されてから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界隈はこれからもまだまだ悩ましい時代が続きそうな予感がしますね:)