Help us understand the problem. What is going on with this article?

TailwindCSS入門 ~ Utility First + デザインシステムの構築 ~

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や、marginborder-radiusなど、あらゆるスタイルに飛びとびでクラスがあり、

  • 意思決定コストを下げる

ことができます。

文字の大きさを「40pxにするか42px」にするか、悩むことは相当こだわりがない限り、無駄だったりします。

また、既にあるクラスからピックアップすることで、

  • チーム内でテーマを統一する

ことができます。

そうしたスタイルガイド、ひいてはデザインシステムの構築を可能にするのが、Tailwindです。

そして、Tailwindを使う更なるメリットは、

  • 容易にカスタマイズ可能である

ことです。

私たちは「ユーティリティを自ら創りだす」ことができます。

そういった意味で、Tailwindは

Utility Firstなフレームワーク

なのでした。

では、Tailwindを用いた

  • カスタマイズ
  • デザインシステムの構築

をしていきます。

インストール

まずは、npmでインストールをします。

npm install --save-dev tailwindcss

最小限だと、styles.cssを作り、

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のプラグインが用意されています。

postcss.config.js
module.exports = {
  plugins: [
    require('tailwindcss')
  ]
}

こうすることで、Tailwindのビルドをバンドラーの中ですることができます。

カスタマイズする

早速、カスタマイズをしていきます。
下記のコマンドを打つと、設定用ファイルが作成されます。

npx tailwind init

ルートディレクトリに「tailwind.config.js」が作成されました。

tailwind.config.js
module.exports = {
  theme: {
    extend: {}
  },
  variants: {},
  plugins: []
}

以下のプロパティがありますね。

  • theme
    • extend
  • variants
  • plugins

それぞれについて、説明していきます。

Theme

Themeではあらゆる値を定義することができます。

  • 画面のブレークポイントの定義
  • カラーパレットの定義
  • フォントサイズの値の定義 etc…

例えば、画面のブレークポイントを定義する際は、

tailwind.config.js
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を使います。

tailwind.config.js
// デフォルトのテーマの値と組み合わせることも可能
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の規定値は、下記のようになっています。

tailwind.config.js
module.exports = {
  variants: {
    fontSize: ['responsive'],
  },
  ...
}

上記の例だと、'hover'がないので、hover:text-*は生成されません。
生成したい場合は、こうします。

tailwind.config.js
module.exports = {
  variants: {
    fontSize: ['responsive', 'hover'],
  },
  ...
}

また、この設定だと複合的なクラスが生成されます。

例)sm:hover:text-lg

「640px以上で、マウスがのった時」にtext-lgと同じスタイルが適用される

非常に便利です。

が、その一方で、組み合わせによってはクラスが増え、ファイルサイズが大きくなります。

そこに対する考慮があってか、hoverfocusについては、既定で適用されていないクラスが多いです。

規定値については、下記で確認してください。

https://tailwindcss.com/docs/configuring-variants#default-variants-reference

カスタム variants

例えば、下記のようにカスタムのvariantsを設定することもできます。
(プラグインについては後述します。)

tailwind.config.js
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; }

また、これらは順序の通りに生成されます。

tailwind.config.js
module.exports = {
  variants: {
    fontSize: ['custom', 'hover'],
  },
  ...
}
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になります。
よって、

tailwind.config.js
module.exports = {
  variants: {
    fontSize: ['custom', 'default', 'hover'],
  },
  ...
}

とできます。

プラグインの作成

プラグインを追加することで、独自のクラスを追加することができます。
例えば、sample-classというクラスを追加したい場合は、下記のようにします。

tailwind.config.js
module.exports = {
  plugins: [
    function({ addUtilities }) {
      const newUtilities = {
        ".sample-class": {
          // CSS-in-JS 構文になる
          backgroundColor: "red"
        }
      };

      addUtilities(newUtilities);
    }
  ]
};

pluginsプロパティに、関数を追加するだけで、プラグインを定義することができます。

これにより、サードパーティのプラグインの開発・利用ができます。

実際に作る際の例を記事にしてみました。

そのほかにも、カスタムvariantsを追加したり、
themeへアクセスして、クラスを動的に生成させることなどができます。

全部書いてると、長すぎて死にそうなんで、
詳しくは、こちらの公式ページを参照してください。

https://tailwindcss.com/docs/plugins

恐らく、addUtilitiesaddComponentsaddBaseの違いなど
若干の混乱ポイントがあるので、その際はこちらを見て頂くといいかもしれません。

tailwind.config.js その他のオプション

Prefix

各クラスのプリフィクスを定義できます。

text-lg -> x-text-lg

tailwind.config.js
module.exports = {
  prefix: 'x-',
}

ただし、下記のように書いたクラスには適用されません。
(プラグインで作ったクラスにはちゃんと付きます。)

styles.css
@tailwind base;
@tailwind components;
@tailwind utilities;

.my-class { ... }

結果:

output.css
.my-class { ... }

/* プラグインで追加した場合 */
.x-custom-class { ... }

Important

trueにすることで、すべてのクラスに!importantが付きます。

tailwind.config.js
module.exports = {
  important: true,
}

結果:

.text-lg { 
  font-size: 1.125rem !important;
}

他のCSSと混在する際に、使うかもしれません。

Seperator

variantsを利用する際の、区切り文字を設定できます。

tailwind.config.js
module.exports = {
  separator: "_",
}

結果:

.hover_text-lg:hover { 
  font-size: 1.125rem !important;
}

公式によると、Pug等のテンプレートエンジンへの対応らしいです。

Core Plugins

ユーティリティの有効・無効を定義できます。

下記のようにすることで、fontSizeのクラスが出力されなくなります。

tailwind.config.js
module.exports = {
  corePlugins: {
    fontSize: false,
  }
}

逆にfontSizeのみにしたいときは、こうします。

tailwind.config.js
module.exports = {
  corePlugins: [
    "fontSize"
  ]
}

これらを用いることで、ファイルサイズを調整できます。

後述しますが、Tailwindの中で、「Preflight」と呼ばれている部分があります。
Core Pluginは、Preflightを無効にしたい際にも利用可能です。

tailwind.config.js
module.exports = {
  corePlugins: {
    preflight: false,
  }
}

設定可能なプロパティは、下記をご覧ください。

https://tailwindcss.com/docs/configuration/#core-plugins

ディレクティブ

Tailwindでは、ディレクティブによるカスタマイズをすることも可能です。

ディレクティブは、CSSの中で@xxxxというふうに使用することがきでます。

@tailwind base;

ここでは、いくつかのディレクティブを紹介していきます。

@tailwind

実は、Tailwind CSSはいくつかのセクションに分かれています。

これらを読み込むタイミングを指定するのが@tailwindです。

最初に作成したCSSファイルを見てみましょう。
base -> components -> utilitiesの順になります。

styles.css
@tailwind base;

@tailwind components;

@tailwind utilities;

では、それぞれのセクションについて説明していきます。

base

CSS Resetなど、すべてのベースとなるスタイルが定義されています。

プラグインの、addBaseではこのセクションへのクラスの追加ができます。

Preflight

baseに含まれる、CSS Reset(normalize.css + 独自拡張らしいです)などが行われる部分を指します。
その為、CSS Resetを上書きするには、下記のようにします。

styles.css
@tailwind base;

/** baseの後に書く **/
button { ... }

@tailwind components;

@tailwind utilities;

他にもプラグインを用いる方法などいろいろあります。

https://tailwindcss.com/docs/adding-base-styles/

components

コンポーネントクラスが集まっています。
コンポーネントクラスとは、.buttonのようなものです。

現在Tailwindが提供しているコンポーネントクラスは、.containerクラスのみです。

自作コンポーネントクラスの追加は、プラグインのaddComponents関数によってできます。

ただ、あまり複雑なコンポーネントをCSSのみで作成することは公式が推奨していません。
ReactやVue.jsを用いることを推奨しています。

utilities

.flex.opacity-0などが含まれています。

Tailwindの大部分を占めるものになります。

プラグインでは、addUtilitiesにより追加ができます。

screens

レスポンシブvariantsによるメディアクエリの記述は、既定ではファイルの末尾につきます。

@tailwind screensにより、メディアクエリに関する記述の位置を、移動させることができます。

styles.css
@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 {
  .ull-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 Stable Release

この記事は、v1.0.1(安定版)が出たのを機に書きました。
なので、v1.0.1の前提で書いているので、以前のバージョンを使っている方からすると、少し違って感じるかもしれません。

また、こうしてみると、他のCSS Frameworkとは全く毛色が違うことがわかります。
ですが、決して競合するものではなく、併せて使うのはかなり有意義だと思います。
正直、CSSに対する知識がないと、使うのは厳しいかもしれませんが、
BootstrapやMaterial系のコンポーネントを使う場合でも、細かい調整には必ずCSSの知識が必要です。
他のフレームワークと比較することはあまり意味がなく、
そのフレームワークの特色を活かせるかが肝なので、開発に見合ったものを選択するといいと思います。

これまた余談ですが、公式サイトのランディングページで、
スクロールにより、シームレスにドキュメントに入っていくのは気持ちよさを感じます。

デザインがそうさせているのですから、Tailwindの作者がどれだけデザインを大事にしているかわかるでしょう。

ただ、Tailwind自体は、「良いデザインを作ること」とは直接関係がありません。
あくまで、デザインシステムを構築するためのユーティリティを提供するものだと思っています。
同じような思想を持ち、バニラのCSSを取り扱ってきた方はいると思います。
ただ、それら管理手法をチームや組織内で統一する目的にTailwindを使用するのは有意義かと思います。

あとこんな記事書くくらいなら、Tailwind CSSの日本語化に貢献しようかとも思うんですが、いかんせん英語力も日本語力も自信が無い為、手を出していません。

ドキュメントの日本語化をされている方は、どのくらい英語に詳しいのだろうかと、時々思います。

どうやら、Tailwindはドキュメントの多言語翻訳をするつもりが無いらしいです。

メンテナンスが大変なので、しないとおっしゃっています。

あと、Gridサポートとかもしないらしいです。

拡張しやすいように作ったのだから、好きに拡張してくれと言っています。

そんなこんなで、長くなりましたが、これを機にTailwind CSSを使って、カスタムでかっこいいデザインを自前で作ったり、自分でCSS Frameworkを公開する際の基盤にしてみてはと思います。

ご精読ありがとうございました。

oedkty
無職になり、Quoraにどっぷりはまっています。
https://jp.quora.com/profile/%E5%A4%A7%E6%9E%9D-%E5%85%8B%E8%A1%8C
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした