Tailwind CSS とは
迅速かつ簡単にデザインシステムを構築するためのユーティリティ
を提供するフレームワークです。
これだけではよくわかりませんね。
そこでまずは、TailwindのUtility Firstの概念を、例を交えて説明していきます。
Utility First
Tailwindには.button
のようなクラスはありません。
一方で、.flex
クラスが存在します。
これは、CSSのflexプロパティに対応しています。
.flex {
display: flex;
}
どうして、そのような仕様にしているのでしょうか?
まずは、記載量が減るということです。
これは、Tailwindを使わない場合と使った場合の比較です。
使わない場合
<style>
.sample {
display: flex;
justify-content: center;
}
</style>
<div class="sample"></div>
使った場合
<div class="flex justify-center"></div>
記載量が一気に減りました。
もう一つ、紹介させてください。
画面の幅によってスタイルを切り替える例です。
使わない場合
<style>
.sample {
display: flex;
flex-direction: column;
}
@media (min-width: 640px) {
.sample {
display: flex;
flex-direction: row;
}
}
</style>
<div class="sample">
<div>a</div>
<div>b</div>
</div>
使った場合
<div class="flex flex-col sm:flex-row">
<div>a</div>
<div>b</div>
</div>
メディアクエリを書かなくていい分、簡潔になりました。
このようにTailwindでは、
- CSS Propertyに対応するクラス(e.g.
.flex
) - 特定のブレークポイントや、疑似クラスに対応するクラス(e.g.
.sm:font-lg
.hover:flex-row
)
が用意されていて、単一のクラスで様々なスタイルを表現でき
記載量が大きく減る為、コードの可読性が上がります。
デザインシステム
Tailwindが提供するクラスの特徴として、下記のようなものがあります。
文字の色を表します。
-
text-red-100
(薄い赤) text-red-200
text-red-300
text-red-400
text-red-500
text-red-600
text-red-700
text-red-800
-
text-red-900
(濃い赤)
よくあるカラーパレットですが、これと同じことがフォントサイズ等でも可能です。
-
text-xs
(小さい) text-sm
-
text-base
(デフォルトのサイズ) text-lg
text-xl
-
text-2xl
(大きい)※6xlまであります。
そのほかにも、width
や、margin
・border-radius
など、あらゆるスタイルに飛びとびでクラスがあり、
- 意思決定コストを下げる
ことができます。
文字の大きさを「40pxにするか42px」にするか、悩むことは相当こだわりがない限り、無駄だったりします。
また、既にあるクラスからピックアップすることで、
- チーム内でテーマを統一する
ことができます。
そうしたスタイルガイド、ひいてはデザインシステムの構築を可能にするのが、Tailwindです。
そして、Tailwindを使う更なるメリットは、
- 容易にカスタマイズ可能である
ことです。
私たちは「ユーティリティを自ら創りだす」ことができます。
そういった意味で、Tailwindは
Utility Firstなフレームワーク
なのでした。
では、Tailwindを用いた
- カスタマイズ
- デザインシステムの構築
をしていきます。
インストール
まずは、npmでインストールをします。
npm install --save-dev tailwindcss
最小限だと、styles.cssを作り、
@tailwind base;
@tailwind components;
@tailwind utilities;
下記のコマンドを実行すると、output.cssがビルドされます。
npx tailwind build styles.css -o output.css
あとは、HTMLから読み込むだけで利用できます。
<link rel="stylesheet" href="../output.css" />
ソースバンドラーを利用する場合
Webpackなどを用いる場合は、PostCSSのプラグインが用意されています。
module.exports = {
plugins: [
require('tailwindcss')
]
}
こうすることで、Tailwindのビルドをバンドラーの中ですることができます。
カスタマイズする
早速、カスタマイズをしていきます。
下記のコマンドを打つと、設定用ファイルが作成されます。
npx tailwind init
ルートディレクトリに「tailwind.config.js」が作成されました。
module.exports = {
theme: {
extend: {}
},
variants: {},
plugins: []
}
以下のプロパティがありますね。
-
theme
extend
variants
plugins
それぞれについて、説明していきます。
Theme
Themeではあらゆる値を定義することができます。
- 画面のブレークポイントの定義
- カラーパレットの定義
- フォントサイズの値の定義 etc…
例えば、画面のブレークポイントを定義する際は、
module.exports = {
theme: {
screens: {
small: '500px',
medium: '800px',
large: '1024px',
},
},
...
}
とします。こうすると、
text-sm
- 小さめの文字のスタイル
というクラスに対して、
small:text-sm
- viewportの幅が500px以上の要素に対するスタイル
というクラスがビルド時に生成され、使用できます。
<!-- 大きい画面では文字が大きくなる -->
<button class="text-sm small:text-lg">
extend
前の例だと、既定値を上書きしてしまいます。
Tailwindでは既定で、
-
sm:
640px以上の画面に適用される -
md:
768px以上の画面に適用される -
lg:
1024px以上の画面に適用される -
xl:
1280px以上の画面に適用される
が存在しますが、まるごと上書きされてしまいます。
よって既存のテーマを拡張したい場合は、extend
を使います。
// デフォルトのテーマの値と組み合わせることも可能
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
theme: {
// extend プロパティの中に書く
extend: {
screens: {
// xs:w-10で、480px幅以上で、w-10のスタイルが適用されるようになる
xs: '480px'
},
fontFamily: {
sans: [
"メイリオ",
defaultTheme.fontFamily.sans
]
}
}
},
...
}
これで元から存在するクラスを利用できます。
<!-- xs:text-* と sm:text-* が共存される -->
<button class="text-sm xs:text-base sm:text-lg">
すべての値をきっちり決めて管理したいわけでなければ、
既にあるTailwindのクラスを変更・拡張して使っていくことになるでしょう。
Variants
前述したとおり、Tailwindでは、定義されているクラスに対して
レスポンシブなクラスや、疑似クラスを用いたクラスがビルド時に生成されます。
-
sm:text-lg
- 画面が640px以上の時に、text-lg
と同じスタイルが適用される -
hover:text-lg
- マウスを乗せた時に、text-lg
と同じスタイルが適用される
variantsを設定すると、これらのクラスを生成するかどうかをコントロールできます。
例えば、font-size
の規定値は、下記のようになっています。
module.exports = {
variants: {
fontSize: ['responsive'],
},
...
}
上記の例だと、'hover'
がないので、hover:text-*
は生成されません。
生成したい場合は、こうします。
module.exports = {
variants: {
fontSize: ['responsive', 'hover'],
},
...
}
また、この設定だと複合的なクラスが生成されます。
例)sm:hover:text-lg
「640px以上で、マウスがのった時」に
text-lg
と同じスタイルが適用される
非常に便利です。
が、その一方で、組み合わせによってはクラスが増え、ファイルサイズが大きくなります。
そこに対する考慮があってか、hover
やfocus
については、既定で適用されていないクラスが多いです。
規定値については、下記で確認してください。
カスタム variants
例えば、下記のようにカスタムのvariantsを設定することもできます。
(プラグインについては後述します。)
module.exports = {
variants: {
fontSize: ['custom'],
},
plugins: [
// カスタムのvariants追加
function({ addVariant, e }) {
addVariant("custom", ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
// .custom:some-classとなる
return `.${e(`custom${separator}${className}`)}`;
});
});
},
]
...
}
こうすると、下記のようなCSSが生成されます。
.text-lg { font-size: 1.125rem; }
.custom\:text-lg { font-size: 1.125rem; }
また、これらは順序の通りに生成されます。
module.exports = {
variants: {
fontSize: ['custom', 'hover'],
},
...
}
.text-lg { font-size: 1.125rem; }
.custom\:text-lg { font-size: 1.125rem; }
.hover\:text-lg:hover { font-size: 1.125rem; }
では、下記のような順序にしたいときには、どうするのでしょうか?
.custom\:text-lg { font-size: 1.125rem; }
/* 何もついていないクラスをcustomより優先させたい */
.text-lg { font-size: 1.125rem; }
.hover\:text-lg:hover { font-size: 1.125rem; }
text-lg
のような無印クラスはdefault
variantsになります。
よって、
module.exports = {
variants: {
fontSize: ['custom', 'default', 'hover'],
},
...
}
とできます。
プラグインの作成
プラグインを追加することで、独自のクラスを追加することができます。
例えば、sample-class
というクラスを追加したい場合は、下記のようにします。
module.exports = {
plugins: [
function({ addUtilities }) {
const newUtilities = {
".sample-class": {
// CSS-in-JS 構文になる
backgroundColor: "red"
}
};
addUtilities(newUtilities);
}
]
};
plugins
プロパティに、関数を追加するだけで、プラグインを定義することができます。
これにより、サードパーティのプラグインの開発・利用ができます。
そのほかにも、カスタムvariantsを追加したり、
themeへアクセスして、クラスを動的に生成させることなどができます。
全部書いてると、長すぎて死にそうなんで、
詳しくは、こちらの公式ページを参照してください。
恐らく、addUtilities
とaddComponents
、addBase
の違いなど
若干の混乱ポイントがあるので、その際はこちらを見て頂くといいかもしれません。
tailwind.config.js その他のオプション
Prefix
各クラスのプリフィクスを定義できます。
text-lg
-> x-text-lg
module.exports = {
prefix: 'x-',
}
ただし、下記のように書いたクラスには適用されません。
(プラグインで作ったクラスにはちゃんと付きます。)
@tailwind base;
@tailwind components;
@tailwind utilities;
.my-class { ... }
結果:
.my-class { ... }
/* プラグインで追加した場合 */
.x-custom-class { ... }
Important
true
にすることで、すべてのクラスに!important
が付きます。
module.exports = {
important: true,
}
結果:
.text-lg {
font-size: 1.125rem !important;
}
他のCSSと混在する際に、使うかもしれません。
Seperator
variantsを利用する際の、区切り文字を設定できます。
module.exports = {
separator: "_",
}
結果:
.hover_text-lg:hover {
font-size: 1.125rem !important;
}
公式によると、Pug等のテンプレートエンジンへの対応らしいです。
Core Plugins
ユーティリティの有効・無効を定義できます。
下記のようにすることで、fontSizeのクラスが出力されなくなります。
module.exports = {
corePlugins: {
fontSize: false,
}
}
逆にfontSizeのみにしたいときは、こうします。
module.exports = {
corePlugins: [
"fontSize"
]
}
これらを用いることで、ファイルサイズを調整できます。
後述しますが、Tailwindの中で、「Preflight」と呼ばれている部分があります。
Core Pluginは、Preflightを無効にしたい際にも利用可能です。
module.exports = {
corePlugins: {
preflight: false,
}
}
設定可能なプロパティは、下記をご覧ください。
ディレクティブ
Tailwindでは、ディレクティブによるカスタマイズをすることも可能です。
ディレクティブは、CSSの中で@xxxx
というふうに使用することがきでます。
@tailwind base;
ここでは、いくつかのディレクティブを紹介していきます。
@tailwind
実は、Tailwind CSSはいくつかのセクションに分かれています。
これらを読み込むタイミングを指定するのが@tailwind
です。
最初に作成したCSSファイルを見てみましょう。
base -> components -> utilitiesの順になります。
@tailwind base;
@tailwind components;
@tailwind utilities;
では、それぞれのセクションについて説明していきます。
base
CSS Resetなど、すべてのベースとなるスタイルが定義されています。
プラグインの、addBase
ではこのセクションへのクラスの追加ができます。
Preflight
base
に含まれる、CSS Reset(normalize.css + 独自拡張らしいです)などが行われる部分を指します。
その為、CSS Resetを上書きするには、下記のようにします。
@tailwind base;
/** baseの後に書く **/
button { ... }
@tailwind components;
@tailwind utilities;
他にもプラグインを用いる方法などいろいろあります。
components
コンポーネントクラスが集まっています。
コンポーネントクラスとは、.button
のようなものです。
現在Tailwindが提供しているコンポーネントクラスは、.container
クラスのみです。
自作コンポーネントクラスの追加は、プラグインのaddComponents関数によってできます。
ただ、あまり複雑なコンポーネントをCSSのみで作成することは公式が推奨していません。
ReactやVue.jsを用いることを推奨しています。
utilities
.flex
や.opacity-0
などが含まれています。
Tailwindの大部分を占めるものになります。
プラグインでは、addUtilities
により追加ができます。
screens
レスポンシブvariantsによるメディアクエリの記述は、既定ではファイルの末尾につきます。
@tailwind screens
により、メディアクエリに関する記述の位置を、移動させることができます。
@tailwind base;
/** メディアクエリを含んだクラス(.sm\:font-boldなど)が最初に来る **/
@tailwind screens;
@tailwind components;
@tailwind utilities;
ただ基本的には、特定のブレークポイントに対するクラスを追加した場合、そちらを優先すべきでしょうから、そこまで位置を変更する需要はないかもしれません。
@apply
classを複合した新しいクラスを作成することができます。
例えば、
.btn {
@apply font-bold py-2 px-4 rounded;
}
のようにして、ボタンに関する記述を一つにまとめることができます。
使いどころとしては、コンポーネント内で無尽蔵にクラスを書くよりも、ある程度CSSでまとめてから使いたい時でしょうか。
<template>
<button class="font-bold py-2 px-4 rounded"></button>
</template>
<template>
<button class="btn"></button>
</template>
<style>
.btn {
@apply font-bold py-2 px-4 rounded;
}
</style>
BEM記法でコンポーネントクラスを使う際などに活躍しそうですね。
注意点としては、レスポンシブや疑似クラスは、applyできません。
.btn {
/* これはできない */
@apply hover:bg-white md:text-lg
}
@variants
これは、例を見た方が早いです。
@variants focus, hover {
.sample { ... }
}
.sample { ... }
.focus\:sample:focus { ... }
.hover\:sample:hover { ... }
variants
プロパティ同様、こちらも順序が適用されます。
@variants hover, focus {
.sample { ... }
}
.sample { ... }
/* hoverが先に来る */
.hover\:sample:hover { ... }
.focus\:sample:focus { ... }
カスタムで作ったvariantsも利用可能です。
@responsive
レスポンシブ関連のディレクティブになります。
theme.screen
プロパティからコードを生成できます。
@responsive {
.full-width {
width: 100%;
}
}
.full-width {
width: 100%;
}
@media (min-width: 640px) {
.sm\:full-width{
width: 100%;
}
}
@media (min-width: 768px) {
.md\:full-width{
width: 100%;
}
}
/* ...ほかのサイズについても続く */
@screen
こちらも、レスポンシブ関連です。
theme.screen
プロパティから任意のサイズを選択して、使うことができます。
@screen sm {
/* ... */
}
@media (min-width: 640px) {
/* ... */
}
Tailwind ファンクション
最後に、ファンクションを紹介しておきます。
@theme
theme
プロパティで定義している値にアクセスできます。
.header {
font-size: theme('fontSize.lg');
}
.header {
font-size: 1.125rem;
}
以上が、カスタマイズに関する部分のざっくりとした説明になります。
公式サイトを見て頂ければ、より多くの情報が得られるかと思います。
是非、Tailwind CSSを始めてみましょう。
さいごに
この記事は、v1.0.1(安定版)が出たのを機に書きました。
なので、v1.0.1の前提で書いているので、以前のバージョンを使っている方からすると、少し違って感じるかもしれません。
また、こうしてみると、他のCSS Frameworkとは全く毛色が違うことがわかります。
ですが、決して競合するものではなく、併せて使うのはかなり有意義だと思います。
正直、CSSに対する知識がないと、使うのは厳しいかもしれませんが、
BootstrapやMaterial系のコンポーネントを使う場合でも、細かい調整には必ずCSSの知識が必要です。
他のフレームワークと比較することはあまり意味がなく、
そのフレームワークの特色を活かせるかが肝なので、開発に見合ったものを選択するといいと思います。
これまた余談ですが、公式サイトのランディングページで、
スクロールにより、シームレスにドキュメントに入っていくのは気持ちよさを感じます。
デザインがそうさせているのですから、Tailwindの作者がどれだけデザインを大事にしているかわかるでしょう。
ただ、Tailwind自体は、「良いデザインを作ること」とは直接関係がありません。
あくまで、デザインシステムを構築するためのユーティリティを提供するものだと思っています。
同じような思想を持ち、バニラのCSSを取り扱ってきた方はいると思います。
ただ、それら管理手法をチームや組織内で統一する目的にTailwindを使用するのは有意義かと思います。
あとこんな記事書くくらいなら、Tailwind CSSの日本語化に貢献しようかとも思うんですが、いかんせん英語力も日本語力も自信が無い為、手を出していません。
ドキュメントの日本語化をされている方は、どのくらい英語に詳しいのだろうかと、時々思います。
どうやら、Tailwindはドキュメントの多言語翻訳をするつもりが無いらしいです。
あと、Gridサポートとかもしないらしいです。
拡張しやすいように作ったのだから、好きに拡張してくれと言っています。
そんなこんなで、長くなりましたが、これを機にTailwind CSSを使って、カスタムでかっこいいデザインを自前で作ったり、自分でCSS Frameworkを公開する際の基盤にしてみてはと思います。
ご精読ありがとうございました。