はじめに
こんにちは、レバレジーズ株式会社の牛嶋です。 レバレジーズ株式会社で、teratailをはじめとしたサービスの開発に携わっております。現在、teratail管理画面のリニューアルに取り組んでおり、技術選定にあたって、CSSフレームワークとして、tailwindcssを採用しました。
この記事では、tailwindcssを採用した理由や、実際にフロントエンド開発で使ってみて良かった点や困った点を紹介します。弊チームの他のプロジェクトでは、CSS Modulesを採用しているため、それと比較しながら紹介していけたらと思います。
tailwindcssとは
tailwindcssとは、CSSフレームワークの一つです。最大の特徴として、ユーティリティファーストなアプローチでデザインを組み立てていく点が挙げられます。
CSS Modulesやstyled-componentでは、デザインをゼロベースで構築することができますが、CSSを一から書かなくてはならず、また、それの運用コストも発生します。 また、BootstrapやMUIなどのCSSフレームワークでは、コンポーネントが事前に用意されているので、効率的にデザイン実装ができる反面、デザインに画一性が生まれてしまいます。
その点、tailwindcssでは事前に提供されている低レベルのユーティリティクラスを用いて、実装速度を担保したまま、独自のデザインを組み立てることができます。
ユーティリティクラスとは
tailwindcssでは、m-6, text-whiteなどのクラスをユーティリティクラスと呼んでいます。これら一つ一つのユーティリティクラスには、対応するCSSプロパティが用意されています。
tailwindcssは、MUIなどが提供している事前に用意されたコンポーネントは提供しておらず、プリミティブなCSSプロパティに対応したユーティリティクラスを提供しています。これらをHTMLのclass属性に追加していくことにより、デザインを構築していきます。
実装例
弊チームでは、tailwindcssとCSS Modulesを採用しているので、それらの実装例を見ていきます。
tailwindcssでは、CSSを記述することなく、ユーティリティクラスを用いて、インラインスタイルでデザイン構築を行なっていきます。 一方、CSS Modulesでは、JSXファイルとSCSSファイルをわけて、デザインを構築していきます。
tailwindcssの場合
// 公式サイト(https://tailwindcss.jp/docs/utility-first)から引用 const ChitChat = () => { return ( <div className="max-w-sm mx-auto flex p-6 bg-white rounded-lg shadow-xl"> <div className="flex-shrink-0"> <img className="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo"> </div> <div className="ml-6 pt-1"> <h4 className="text-xl text-gray-900 leading-tight">ChitChat</h4> <p className="text-base text-gray-600 leading-normal">You have a new message!</p> </div> </div> ) } export default ChitChat;
CSS Modulesの場合
// 公式サイト(https://tailwindcss.jp/docs/utility-first)から引用 import styles from “./chitChat.modules.scss” const ChitChat = () => { return ( <div className={styles.chatNotification}> <div className={styles.chatNotificationLogoWrapper}> <img className={styles.chatNotificationLogo} src="/img/logo.svg" alt="ChitChat Logo"> </div> <div className={styles.chatNotificationContent}> <h4 className={styles.chatNotificationTitle}>ChitChat</h4> <p className={styles.chatNotificationMessage}>You have a new message!</p> </div> </div> ) } export default ChitChat;
.chatNotification { display: flex; max-width: 24rem; margin: 0 auto; padding: 1.5rem; border-radius: 0.5rem; background-color: #fff; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); } .chatNotificationLogo-wrapper { flex-shrink: 0; } .chatNotificationLogo { height: 3rem; width: 3rem; } .chatNotificationContent { margin-left: 1.5rem; padding-top: 0.25rem; } .chatNotificationTitle { color: #1a202c; font-size: 1.25rem; line-height: 1.25; } .chatNotificationMessage { color: #718096; font-size: 1rem; line-height: 1.5; }
なぜtailwindcssを導入したか
tailwindcssは、「チームとして新しい技術にチャレンジしたかった」という理由に加え、下記の効果を期待して導入しました。
- 実装速度の向上
- CSS設計と運用コストの削減
- スコープが担保した上でのデザイン
- CSSファイルサイズの最適化
詳細は以下の章で説明させていただきます。
メリット
実装速度が向上する
tailwindcssはユーティリティクラスの他にも、hoverなどの容易に適用することができる疑似クラスバリアントや、レスポンシブデザインを容易に実現できる、レスポンシブユーティリティバリアントを提供しています。
以下は一例です。mdをプレフィックスとしてつけることで、指定されたスタイルに「min-width: 768px」のメディアクエリが適用されます。
// 公式サイト(https://tailwindcss.jp/docs/responsive-design)から引用 <div className="md:flex"> <div className="md:flex-shrink-0"> <img className="rounded-lg md:w-56" src="https://images.unsplash.com/photo-1556740738-b6a63e27c4df?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=448&q=80" width="448" height="299" alt="Woman paying for a purchase"> </div> <div className="mt-4 md:mt-0 md:ml-6"> <div className="uppercase tracking-wide text-sm text-indigo-600 font-bold">Marketing</div> <a href="#" className="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">Finding customers for your new business</a> <p className="mt-2 text-gray-600">Getting a new business off the ground is a lot of hard work. Here are five ideas you can use to find your first customers.</p> </div> </div>
最初こそ慣れるまで時間がかかると思いますが、ある程度の書き方を覚えてしまえば、CSSを直接で書くよりも速く実装することが可能だと思います。
CSS設計と運用コストの軽減
tailwindcssを用いると、ユーティリティクラスを直接class属性に記述するだけなので、CSSのクラス設計をする必要がなくなります。CSS設計の規則を考える必要もないですし、それらを基準にして、class名を考える必要もなくなります。
また、CSSファイルを作成する必要がなくなるため、ファイルの運用コストもなくなります。そもそもファイルを作成しないので、CSSが肥大化することもありません。
スコープが担保されるので、安全にデザインを変更できる
tailwindcssは基本的にclass属性に記述していくので、HTMLファイルに変更が閉じられ、自然とデザインを適用するスコープが担保されます。
そのため、任意の箇所のデザインを変更することになっても、影響範囲を考えることなく、安全にデザインを変更することができます。
CSSファイルのサイズを小さく出来る
tailwindcssはPurgeCSSを採用しており、本番用にビルドする場合には、未使用のスタイルを自動的に削除します。
その結果、プロジェクトで使用しているスタイルのみを出力したCSSファイルが生成され、ビルドサイズが小さくなります。
デメリットと対応方法
慣れるまではクラスを探すのが面倒?
tailwindcssのユーティリティクラスに慣れるまでには、CSSプロパティに対応するクラスを探すのに苦労する可能性があります。最初のうちは多少時間を取られると思います。
しかし、エディタのプラグインを使えばある程度負担を軽減することができます。 例えば、VS Codeで提供されているプラグインの「Tailwind CSS InteliSense」を利用すれば、クラス名の自動補完等の機能を使うことができ、比較的開発が楽になるかと思います。
メンテナンス性が落ちる?
ユーティリティクラスをクラス属性に書いていくと、多くのクラスがクラス属性内に記述されることになります。結果的に、そのクラスに記述された内容が何をしているかわからない状態になることもあると思います。
その点、tailwindcssはapplyというディレクティブを提供しており、既存のユーティリティクラスを独自のカスタムCSSにインライン化することができます。
また、別の方法として、必要な単位でコンポーネントを抽出する方法があります。
個人的には、後者の方法の方がメリットを享受できると考えています。具体的な理由として、Reactをはじめとするコンポーネント志向のフレームワークとの相性が良い点、また無用なユーティリティクラスを増やすことがない点などがあげられます。
提供されていないCSSが必要な場合はどうする?
tailwindcssのユーティリティクラスで提供されていないデザインを実装したい場合があるかもしれません。基本的にデフォルトで実装するには十分な量のユーティリティクラスが提供されています。
しかし、万が一足りなくなった場合でも容易に拡張することができます。公式サイトで独自のユーティリティクラスを追加するためのベストプラクティスが紹介されています。
今後の展望
上記メリットでは紹介しなかったのですが、tailwindcssには設定ファイル(tailwind.config.js)が存在します。設定ファイル上で、自分たちのデザインシステムに沿って、tailwindcssをカスタマイズすることができます。以下が設定ファイルの例です。
// Example `tailwind.config.js` file // 公式より引用(https://tailwindcss.jp/docs/configuration) module.exports = { important: true, theme: { fontFamily: { display: ['Gilroy', 'sans-serif'], body: ['Graphik', 'sans-serif'], }, extend: { colors: { cyan: '#9cdbff', }, margin: { 96: '24rem', 128: '32rem', }, }, }, variants: { opacity: ['responsive', 'hover'], }, }
上記のように、設定ファイルでデザインをカスタマイズすることが可能なので、tailwindcssはデザインシステムと非常に相性がいいと考えています。
弊チームでは、今後サービスの横展開も考えており、その際にデザインシステムの作成とともに、tailwindcssを利用したUIライブラリを実装していけたらと考えています。
最後に
CSSフレームワークにtailwindcssを採用したことで、設計面での負担軽減や、実装速度向上等、開発面で多くのメリットを享受することができました。
今後の展望で記載した通り、個人的にtailwindcssはデザインシステムを組み合わせてこそ真価を発揮します。サービスが展開していくことも考え、tailwindcssをベースとしたUIライブラリを構築していけたらと考えています。今後の取り組みなどについては、また別の機会で知見を共有できたらと思います。
私は現在、新卒2年目なのですが、今回の技術選定を担当させてもらいました。弊社には、意思決定に合理性と納得性があれば年次に関係なく、自由に発言や提案ができる環境があります。 「主体性を持って働きたい人」や「新しい技術にチャレンジしたい人」には最適な環境だと思うので、興味のある方はぜひ一緒に働きましょう。