【Next.js】CSS戦略について色々調べた結果、Tailwindが一番良かったと言う話

2024/01/13に公開

Next.jsでの新規プロダクト開発に携わって、スタイリングの技術選定をする機会がありました。
スタイリング選定にあたって色々な技術を調べてみたので、それらの比較と最終的になんの技術が良かったかを書きます。

結論: Tailwind + Tailwind UIフレームワークが最強

結局Tailwindです。ありがとうございました。

…としかし、これで終わったら元も子もないので
ここに至った経緯と、なぜTailwindが良いと思ったかを後述します!

Next.jsがサポートしている技術を見てみる

Next.jsのドキュメントには、大きく以下の5つをサポートしていると書かれています。

  • Global CSS
  • CSS Modules
  • Tailwind CSS
  • Sass
  • CSS-in-JS

これらを比較して最終的にTailwindが一番良いと感じたわけですが、
他の技術が候補から外れた理由をまとめます!

Tailwindと他のCSS記法を比べてみる

Global CSSが候補から外れた理由

Global CSSは、簡単にいうと普通のCSSです。
hoge.cssのようなファイル名で定義し、必要なページにスタイルを読み込みます。
通常のCSSを使うよりは、何か他の技術を使った方がいいという理由で候補から外れました。

CSS-in-JSが候補から外れた理由

CSS-in-JSはJavaScritを用いてCSSを定義するスタイリング手法です。
CSS-in-JSの中にも様々な技術があり、NextのドキュメントにサポートしているCSS-in-JSのリストが記載されています。

JavaScritを用いてスタイリングをすると、以下のようなメリットがあります。

  • CSSのスコープができるため、他のスタイルに影響しない
  • JavaScriptのロジックを元に、動的にスタイリングできる
  • ESLintやTypeScriptと組み合わせて、未使用のCSSを検出できたりする

CSSだけでは実現できないことも、JavaScriptのロジックを利用して実現できます。
裏を返すと学習コストが高いです。

CSS-in-JSを経験したことがあるエンジニアであれば、スムーズに導入できるかもしれませんが、慣れていないエンジニアにとってはキャッチアップに時間がかかりそうだと感じました。

私自身も半年前までWeb制作がメインであり、CSS-in-JSの経験がありませんでした。なのでこの選択は良かったと感じています。

余談ですがvanilla-extractはすごく魅力的なCSS-in-JSだったので、何かの機会で使ってみたいなーと思っています🐧

SassとCSS Modulesが候補から外れた理由

  • CSS Modules
  • Sass(SCSS)

この2つは組み合わせて使うことができるため、Sass記法のCSS Moulesとして使うことを考えていました。
以下、CSS Moules = Sass記法のCSS Modulesとして進めます。

CSS ModulesとTailwindの2択で悩みましたが、最終的にはTailwindに軍配が上がりました。

CSS Modulesが候補から外れた理由は以下の2つです。

  • ディレクトリ構造やCSS設計について考えるのが大変だったため
  • グローバルなスタイルとの棲み分けが難しいため

まず課題に上がったのが、ディレクトリ構成やCSS設計についてです。

ディレクトリ構成は、コンポーネントとSassファイルを1対1にするのが良いと思いました。

次にCSS設計は無難にBEMが良いだろうと思いました。しかしここで壁にぶつかります。
JavaScriptは変数名に-を含められないため、通常のBEM運用ができないのです。

<div className={`${style.button__primary--active}`}>ボックス</div> // ❌ "-"が使えない

さらにグローバルなスタイルをどこに定義するかも悩みました。
グローバルなスタイルだからスコープを取っ払ってこんな感じ?

<div className={`global-bg-color ${component.boxStyle}`}>ボックス</div>

それともグローバルなスタイルもオブジェクトで読み込んだ方がわかりやすい?

<div className={`${global.bgColor} ${component.boxStyle}`}>ボックス</div>

…思ったより考えること多いなと。ハマってしまいました。
色々な方がこの辺りを記事にまとめてくれており、ある程度のセオリーもあるだろうからそれほど時間はかからないと思っていたのですが、見通しが甘かったです。
何より大変なのが、ここで決めたルールをチームに浸透させていくことです。

Tailwindであれば、クラス名やCSS設計について考える必要は基本的にありません。

Tailwindにして良かったこと

  • クラス名について議論する必要がない
  • cssファイルの構造について議論する必要がない
  • Tailwindのルールに則って書くので、コードのばらつきが出にくい
  • UIフレームワークを使うと、開発効率が上がる

クラス名やファイル構造について議論する必要がないのは、とてもありがたかったです。
CSSをよく書く方ならであれば一度はこんな経験があるのではないでしょうか?

🧐「ボックスの内側の要素のクラス名は、box-inner?box-content?」
🧐「命名規則はどうする?BEMってみんな知ってるかな?」

このあたりから議論し始めると、かなりの時間を要します。
特に普段バックエンドメインのエンジニアがフロントエンド開発に入る場合は、これらのキャッチアップがかなり大変なのではないかと思います。

Talwindであれば、一定のルールに則ったクラス名指定ができます。
Tailwindのデメリットとして「クラス名が長くて見づらい」がデメリットに挙げられがちですが、個人的には見づらくてもルールの一貫性が保たれている方が大事だと考えます。

さらにTailwindには、TailwindベースのUIフレームワークが存在します。
daisyUIFlowbiteなんかが有名です。
これを用いることで、モーダルやドロワーといった複雑なコンポーネントもサクサク実装できます。

Tailwindにして困ったこと

  • 慣れるまでは、Tailwindの記法に多少違和感
  • configやlinterの設定が大変

Tailwind特有の記法に違和感を感じます。Tailwindを使ったことがない人は、必ずと言っていいくらい違和感を感じるのではないかと思います。
しかし慣れです。3日もすれば慣れます。

Tailwindでのコーディングをサポートしてくれるチートシートがあるので、フル活用しましょう。
擬似要素や小要素など、特殊なスタイリングはチートシートで見つからないことが多いので、キャッチアップが必要です。

よりTailwindを使いこなそうと思うと、tailwind.configやESlintの設定が必要です。

例えばtailwind.configでは、デフォルトのTailwindにないクラスを定義できます。
またESlintではTailwindの構文チェックをして、Tailwindではないクラス名にWargingを出したり、一定の順番にクラスを並び替えたりできます。
一度設定すれば効率的にTailwindの構築ができるのですが、設定にはある程度の知識が必要です。

Tailwind以外の技術が向いているかもしれない場面

ここまでTailwindをべた褒めしてきましたが、Tailwind以外の技術を採用した方が良いかもという場面もあります。(個人的な見解です)

それは大規模プロダクトや既存サービスのリプレイスです。

Tailwindのメリットは、導入のしやすさと、シンプルなルールによる書きやすさだと思っています。
つまり「機動力」です。
スピード感が求められる新規プロダクト開発においては、Tailwindの機動力を活かしていち早くプロダクトをリリースまで持っていくのが良いと思います。

しかし大規模プロダクトやサービスリプレイスとなると話が変わってきます。
時間やお金をかけられる大規模プロダクトであれば、長く運用保守できるようなCSS設計を考えて地盤を固める方が大事なのかもしれないと感じました。
サービスリプレイスに関しても同様で、せっかくリプレイスするのであれば保守性の高いCSS設計にある程度時間を割いても良いのではないかと言う考えです。

今回StoryBookを導入していないので、StoryBookとTailwindの相性もどんな感じなのか気になっています。

まとめ

Tailwindいいよ!!!!!

Discussion