今さら聞けないEmotionとTailwind CSSの比較→利点まとめ
実務ではEmotionを、個人開発はTailwind CSSを使ってスタイルを書いています。両者のメリット・デメリットを比較整理してみました。広く認知されている技術ではありますが、まだ扱ったことのない方向けにそれぞれの魅力が伝わったらなと思います。
▼事前に把握しておくとよさそうなこと(GPT生成)
Tailwind CSSとは?
Tailwind CSSは、ユーティリティファーストという設計思想に基づくCSSフレームワークです。これは、あらゆるデザインを低レベルのユーティリティクラス(原子クラス)を組み合わせて構築する方法を推奨します。これにより、デザインのカスタマイズが容易になり、再利用可能なコンポーネントの作成が不要になります。
コード例:
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Button
</button>
公式サイト:https://tailwindcss.com/
Emotionとは?
Emotionは、CSS-in-JSのライブラリの一つで、JavaScriptを使ってスタイルを書くことができます。React.jsなどのJavaScriptフレームワークと相性が良く、動的にCSSを生成したり、コンポーネントのスコープを維持することが可能です。
コード例:
import { css } from '@emotion/react'
function SomeComponent() {
return <div css={style}>Some text</div>
}
const style = css`
color: hotpink;
`
CSS in JSとは?
CSS in JSは、JavaScriptの中にCSSを書くスタイルのことを指します。これは、React.jsのようなコンポーネントベースのライブラリやフレームワークと一緒に使用されます。これにより、スタイルをコンポーネントに直接関連付け、スコープを維持し、コードの再利用を容易にすることができます。
コード例:
function SomeComponent() {
return <div style={style}>Some text</div>
}
const style = {
color: 'blue',
fontSize: '20px'
};
インラインCSSとは?
インラインCSSは、HTML要素に直接スタイルを適用する方法です。これは、style属性を用いてHTMLタグ内にCSSプロパティを直接記述することで行われます。インラインCSSは独自のスタイルを個々の要素に迅速に適用するのに便利ですが、大規模なプロジェクトではメンテナンスが難しくなる可能性があります。
コード例:
<div style="color: red; font-size: 16px;">Some text</div>
UIコンポーネントライブラリとは?
UIコンポーネントライブラリは、再利用可能なユーザーインターフェース(UI)コンポーネントの集まりです。これらのコンポーネントは、ボタン、フォーム、ナビゲーションバーなど、一般的にウェブアプリケーションで使用されるさまざまなUI要素を含むことができます。
これらのライブラリを使用すると、開発者は独自のUIをゼロから作成するのではなく、既存のコンポーネントを再利用またはカスタマイズして時間を節約することができます。例としては、Material-UI、Ant Designなどがあります。
コード例:
import Button from '@material-ui/core/Button';
function SomeComponent() {
return <Button color="primary">Hello World</Button>
}
まずはコードを比較してみる
メリデメを把握しやすいようGPTになるべく複雑なスタイルを指定した場合のサンプルコードを生成してもらいました。実際も平気でこれくらいの長さになります。(内容ではなく雰囲気を感じ取っていただけたらと)
Tailwind CSSの場合
export const MyComponent = () => {
return (
<div class="overflow-hidden rounded-md bg-gradient-to-r from-green-400 to-blue-500 p-6 shadow-lg transition-all duration-300 hover:from-pink-500 hover:to-yellow-500 dark:bg-gray-800">
<p class="mb-2 text-2xl font-bold text-white underline transition-colors duration-300 hover:text-black dark:hover:text-white md:text-3xl">
Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you
need to build bespoke designs.
</p>
</div>
);
};
Emotionの場合
import { css } from "@emotion/react";
export const MyComponent = () => {
return (
<div css={boxStyle}>
<p css={textStyle}>
Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you
need to build bespoke designs.
</p>
</div>
);
};
const boxStyle = css`
background: linear-gradient(to right, #38a169, #4299e1);
padding: 1.5rem;
border-radius: 0.375rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
overflow: hidden;
transition: all 0.3s;
&:hover {
background: linear-gradient(to right, #ed64a6, #f6ad55);
}
&.dark {
background: #1a202c;
}
`;
const textStyle = css`
color: #fff;
font-size: 2rem;
font-weight: bold;
text-decoration: underline;
margin-bottom: 0.5rem;
transition: color 0.3s;
@media (min-width: 768px) {
font-size: 3rem;
}
&:hover {
color: #000;
.dark & {
color: #fff;
}
}
`;
※スタイルもGPT変換です。おそらく同等のものになってるはず。
Tailwind CSSはインラインで端的に書けてますが、Emotionではスタイルを丁寧に記述しているため冗長になっています。ただ、伝統的なCSSの記法に則っているため、初見での理解のしやすさはEmotionの方が優れています。
ここからはそれぞれに焦点を絞ってメリデメを整理してみます。
個人開発はTailwind CSS一択
私自身はTailwind CSSが好きで、個人開発でTailwind CSS以外の記述でスタイリングを行うことはほぼありません。一度書いたら離れられない魅力がそこにはあります。
Tailwind CSSの何がいいのか?
Tailwind CSSは世界的に注目されているユーティリティファーストなCSSフレームワークです。
どのプロジェクトでのある程度の共通認識を持ってスタイルを当てれるため初期開発学習コストが低く、開発者の入れ替えの多い現場でも活きますし、効率的に書けて修正しやすいためプロトタイプ開発にも向いていたりします。
利点はこのあたりです。
- 依存性がない
- 再利用性が高い
- カスタマイズもできる
- UIコンポーネントが充実している
- 色を適当に指定しても良い感じになる
- スタイル規則を読まなくてもすぐ開発に取り掛かれる
- レスポンシブやダークモードも楽に実装できる
- 慣れたら書きやすい/見やすい/編集しやすい
- 細かいCSSを考える必要がない
- 適度な制約があるためデザインできなくてもそれっぽいUIになる
何よりも気に入ってるのは、依存性がなくいつでもどこでも同じスタイルを割り当てられる点です。カスタマイズやスタイルをまとめたクラスを使用するといった使い方をしなければ、コピペして全く同じスタイルを実現できます。
これによってオープンな開発も進み、UIコンポーネントのデータが充実して楽にUIを作成できるといったベネフィットを享受できたりもしています。
通常のCSSだとメディアクエリなどを考えると分かりやすいと思いますが、たいてい独自のクラスを設定してスタイルを当てているので他プロジェクトでの再現時に設定やスタイルを調整する必要があり、そのルールも変わりがちなのが少し面倒なんですよね。
ありそうな疑問:スタイルの順序とかどう処理してるの?
prettierで専用のプラグイン入れると自動でソートしてくれます。
npm install -D prettier prettier-plugin-tailwindcss
参考:Automatic Class Sorting with Prettier
また、これはVSCodeの拡張機能の方かなと思いますが、予測変換や重複チェックも自動で行ってくれるので開発体験は良いです。
他、スタイルが分からなくなった時は、Tailwind CSSのチートシートで確認しています。
Tailwind CSSの微妙な点
- 好き嫌いが分かれている
- 多少慣れが必要
- コードが見づらくなる
- 複雑なスタイル指定が設定しづらい
- 細かいCSSプロパティに対応したクラスが分からなくなる
- デザインに忠実なスタイルを当てるのは若干苦手
Tailwind CSSの厄介な点は好き嫌いが分かれている点です。SASS記法であれば既存のCSSの延長にあるので誰しもがスタンダードであると認識できますが、TailwindはCSSフレームワークなのでBootstrapのように実務では扱いにくいイメージを持たれることが少なくありません。
個人的にはスタイルの依存性がなくなることで各プロジェクトに対して並列的に好影響を与える可能性が高いと思うものの、全体として導入するには学習コストや後戻りしにくいといったリスクがあるので国内で大々的に業務に採用するには小規模な組織でないと厳しいのかなといった印象を持っています。
業務に取り入れるとしたら、まずは小さな開発から
社内でTailwind CSSを採用するかといった議論があった際は、まずは期間限定でリリースする特設サイトなどの小規模な開発で取り入れてみると良いかもですね。
好き嫌いの問題(食わず嫌いも多いので動かしてみないと分からない)があるので、社内のエンジニア文化と合うかどうかは事前にチェックした方が好ましいかなと。他、ChakraUIのようなUIコンポーネントライブラリを採用する選択肢もあります。
何にせよ個人開発はTailwind CSS一択感あります。
実務ではEmotion
Emotionは伝統的なCSSをjavascriptで記述できるCSS in JSライブラリです。慣れ親しんだCSSに則ってスタイルを記述でき、手軽に動的なスタイルを起こせて誰でも扱いやすいのが魅力です。
Emotionの好きなところ
- 階層化してスタイルを当てやすい
- クラス名やIDを気にする必要がない
- クラスやID指定でもスタイリングできる
- 純粋なCSS/SASSで書けて誰でも使える
- 複雑なスタイリングをしやすい
- スタイルが廃れることがない
実務では用意されたコンポーネントを操作することがほとんどですが、新規でスタイルを作成する際に通常のCSSで書けるので良いですよね。
純粋なCSSを扱う大きな魅力は安心感です。Tailwind CSSは上位互換のCSSフレームワークが現れた時に一気に廃れる可能性があり、その場合、スタイルの記述方法を全く別のものにする必要が出ます。しかし、Emotionが廃れたとしてもCSS自体は今後も活用していけるはず。
デザインデータがあれば、今であればスタイルも自動生成されるので後は開発用に微調整するだけでOKなのも扱いやすかったりします。
Emotionの微妙な点
- スタイルが冗長
- コードに対応しているスタイルが見にくい
- プロジェクト専用のスタイルが増えがち
- 前提としての制約がない分、迷いが生じることがある
Tailwind CSS慣れし過ぎてて感じるのは、CSSを個別に定義して割り当てるのは分かりにくいのではないかという点です。もちろんインラインCSSで書けますし、そうした運用をしている場合もあるかもですが、複雑なスタイルだとコードが冗長になるので分離している方が一般的なはず。
スタイルを分離させると、スタイル名を用意しないといけなく、こういうのもちょっと面倒だったりします。ただ、今はもう慣れたのでEmotionも扱いやすいなと思っています。最終、慣れの方が大事ですね。
それぞれの使い分け
スモール開発はTailwind CSS
個人開発やプロトタイプの構築、シンプルなUIのアプリケーション開発であればTailwind CSSを使うと開発効率が上がるのではと思います。
というのも、TailwindUIやFlowbiteなど、UIコンポーネントライブラリが探せばたくさんあり、細かなデザインを考えることなく構築を進められるからです。お気に入りのテイストのUIライブラリが見つかれば、さくっとUIを作れちゃいます。
例えば、次のようなモーダルをコピペで設置しても、依存性がないためこのまま使えます(Reactベースの場合、Next.js用に記述を調整する程度は発生する)。同様にコピペで扱えるTailwindのUIコンポーネントがネット上に無数にあります。
引用:https://tailwindui.com/components/application-ui/overlays/modals
コピペしただけのもの
<div class="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<!--
Background backdrop, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"></div>
<div class="fixed inset-0 z-10 overflow-y-auto">
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg">
<div class="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
</svg>
</div>
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
<h3 class="text-base font-semibold leading-6 text-gray-900" id="modal-title">Deactivate account</h3>
<div class="mt-2">
<p class="text-sm text-gray-500">Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<button type="button" class="inline-flex w-full justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 sm:ml-3 sm:w-auto">Deactivate</button>
<button type="button" class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto">Cancel</button>
</div>
</div>
</div>
</div>
</div>
構造とスタイルが並列的に記述されているため、修正も非常に楽です。
技術トレンドとしても、Tailwind CSSはここ数年間1番熱いCSSフレームワークであるといって過言ではなく、まだ衰えが見えないのでこのまま使われていきそうです。
デザインが明確に決まってるならEmotion
現状、デザインが明確でそれを忠実に再現していくのであればEmotionの方が適切だと思っています。
Tailwind CSSでも細かなスタイルの調整はできますが、そうなるほど記述が冗長になったり専門性が上がってしまうので、そこまでするならCSSを分離して書いたた方が学習コストもなく管理上も楽な気がしているからです。
また、デザインが確定しているのであればfigmaからCSSもそのまま持ってこれるので、逆にTailwind CSSで書くのが手間になることもあるのかなと。(figmaでTailwind CSSのコードを出力することもできますが、spaceクラスが多用されてたりと個人的に微妙でした。)
その他
Tailwind CSSとUIコンポーネントライブラリについて
Tailwind CSSはUIコンポーネントライブラリとの比較も少ししておきたいです。例えばChakraUIではドロップダウンなどの機能的なUIを楽に実装できる利点はありますが、他のライブラリと組み合わせた時に仕様がグッと複雑になる場合があります。
他のUIコンポーネントライブラリでも同様で美しいUIをサクッと実装できるものの、実装面のリスクを感じることがあります。Tailwind CSSの操作はクラス名を付与するだけなので、どのライブラリと組み合わせるにしてもドキュメント通りの方法で実装できる仕様的な安定感があるのが好きです。
ドロップダウンなどのUIもオープンなコードがたくさんあるので簡単につくれますし。なお、スタイルを当てるのに本当に面倒な時はSASSで当てることもあります。
まとめ
それぞれの記述は運用ルールによって扱いやすさに大きな差は生まれます。今回はTailwind CSSとEmotionの比較でしたが、全体のコードに影響のあるスタックは最終的にはプロダクトやエンジニアの技術や文化適性などを考慮した上での選定が好ましいです。
また、実際に使ってみないと実感できないことも多いです。テックリードが技術を適切に評価しチームのスタックや文化を考慮しつつ積極的に導入を進めることも検討すべきでししょう。
とはいえ気軽に変更できないことの方が多いので、やはり小さい領域で試したりしてエンジニア内で共通認識を確保できた上での判断した方が良さそうだなと。
Discussion