🐈

[2022年]CSS in JSライブラリとフレームワークの調査

2022/12/23に公開

はじめに

株式会社マイベストでフロントエンドエンジニアをしているyamadaです。
普段はmybestというサービスのフロントエンド開発をメインに行ってます。

弊社では現在、デザイナーのスピードと生産性を向上させる事とユーザー体験の品質と一貫性を確保するためにデザインシステムを作成中です。
そのデザインシステムを実装するにあたりCSS周りも刷新する事になりCSS in JSやCSSフレームワークの導入を検討しました。
CSS in JSやCSSフレームワークは様々なものがあり、mybestで使うためには何が相応しいのか調査したのでその結果を簡単にまとめたいと思います。

※大雑把ですが現在のmybestのフロントエンドは下記の構成になってます

  • Next.js
  • TypeScript
  • PostCSS

調査したライブラリとフレームワーク

1. styled-components

https://styled-components.com/

Reactコンポーネントをスタイリングするために開発されたCSS in JSライブラリ。
とても人気があり、有名なサービスでもよく使われている。

メリット

  • propsを通じてTSXからCSSに変数を渡せるので動的なCSSも組みやすい
  • SWCコンパイラの恩恵をうけれる
  • 採用事例が多く、ネット上に様々な記事が投稿されてるので何かハマった時に楽そう

デメリット

  • CSSを設定する要素ごとにコンポーネントを作ることになるため、HTMLとしての可読性が低くい
  • クライアント側でJSがCSSとして解析されるので、何度も処理が走るような部分で記述してしまうとパフォーマンスを落とす

2. Emotion

https://emotion.sh/docs/introduction

上記のstyled-componentsなどにインスパイアされた後発のCSS in JSライブラリでこちらも人気が高い。
オブジェクトスタイルとストリングスタイルの2種類の書き方が用意されていて後者は通常のCSSに近い書き方ができる。

メリット

  • Next.js 12.2から標準でサポートされているので導入が楽
  • ストリングスタイルの書き方が分かりやすく既存のCSSを流用しやすそう
  • SWCコンパイラの恩恵をうけれる
  • パフォーマンスやバンドルサイズの観点でstyled-componentsよりも優れてるらしい
  • 採用事例が多く、ネット上に様々な記事が投稿されてるので何かハマった時に楽そう

デメリット

  • クライアント側でJSがCSSとして解析されるので、何度も処理が走るような部分で記述してしまうとパフォーマンスを落とす

3. CSS Modules

https://github.com/css-modules/css-modules

ReactコンポーネントからCSSをimportして使う。コンポーネント単位でCSSにスコープを作ることができる。

メリット

  • 通常のCSSと同様の記述のため学習コストは低い
  • 通常のCSSが出力されるためCSS in JSよりもロードタイム・ランタイムともにパフォーマンス面で有利
  • CSS in JSのようにスコープが作られる
  • 少し前まではNext.js公式が結構推してたっぽい(現在は不明)

デメリット

  • 将来的に非推奨になる可能性あり

4. Linaria

https://linaria.dev/

Zero-Runtime CSS in JS。
JavaScriptの中にCSSを書けるがビルド後は通常のCSSが出力されるのでパフォーマンスが良い。

Airbnbがこちらを採用したらしく、結果パフォーマンスと開発者体験が向上したらしい
参考: https://medium.com/airbnb-engineering/airbnbs-trip-to-linaria-dc169230bd12

メリット

  • Emotionのストリングスタイルと同じ書き方ができる
    • Emotionの場合はCSS属性に値を渡すが、こちらはclassNameに渡せる
  • 通常のCSSが出力されるため他のCSS in JSよりもロードタイム・ランタイムともにパフォーマンス面で有利

デメリット

  • 今のところNext.js 13で使えないっぽい
    • 導入するにはnext-linariaというライブラリを使う事になるがNext.js 13に対応してないし全然更新されてない
    • Next.js 13のappディレクトリに対応されていない
    • SWCサポートが無さそう

5. vanilla-extract

https://vanilla-extract.style/

こちらもZero-Runtime CSS in JS。
通常のCSSやCSS modulesのように別ファイルでCSS(*.css.ts)を管理する事になる。

メリット

  • TypeScriptをプリプロセッサとして用いており型安全なCSSを書くことができる
    • TypeScriptでStyleを書くことになるので当然TypeScriptと相性が良い
    • ↑なのでVS Codeを使った時の補完が良い感じらしい
  • 通常のCSSが出力されるため他のCSS in JSよりもロードタイム・ランタイムともにパフォーマンス面で有利

デメリット

  • オブジェクト形式での記法であるため従来のCSSとは記法が異なる
  • 新しめのライブラリのためか情報が少ない印象を受ける

6. Tailwind

人気のユーティリティファーストなCSSフレームワーク。
フレームワーク側で用意されたユーティリティclassをHTMLに当ててスタイリングしていく。

https://tailwindcss.com/

メリット

  • CSSを書かなくて良い
  • 命名で悩む事がない
  • CSSファイルのサイズを小さくできる
    • PurgeCSSの導入は必須
    • パフォーマンスは良くなりそう
  • 人気なので情報が多い

デメリット

  • HTML側のclassが冗長になる
  • デザインを100%再現したいケースで無理が出てくる
  • 学習コストが発生する
  • 現在のCSSを流用できない

おわりに

mybestのサイトはパフォーマンスを重要視しているのでZero-Runtime CSS in JSやCSS modulesはとても魅力的でした。
その中でもLinariaは書き方も分かりやすく(通常のCSSのように書ける)、とても良くできたライブラリだったので採用したかったのですがNext.jsへの対応がイマイチという事で断念しました。
結果、書き方が分かりやすくstyled-componentsよりはパフォーマンスが良いという事でEmotionを採用する事にしました。
(CSS Modulesやvanilla-extractはパフォーマンスの観点では魅力的だったのですが、デメリットの部分が大きく採用には至りませんでした)

選定のポイント

  • なるべく通常のCSSの形で書きたい
  • バックエンドのエンジニアもフロントのコードを書くため、なるべく学習コストは発生させたくない
  • パフォーマンスが良い事

現在、Tokens Studio for Figma/Style Dictionaryと連携しながらデザインシステムを開発中なのでまたの機会に紹介できればと思います。

Discussion