記事一覧
Topに戻る
  • TOP
  • Tailwind CSS
  • Tailwind CSSでのフロントエンド開発で素晴らしい開発体験を得よう

Tailwind CSSでのフロントエンド開発で素晴らしい開発体験を得よう

更新日:

by @Panda_Program

Tailwind CSSのサイトのトップページ

CSSが苦手なエンジニアがTailwind CSSを使ってサイトを作ってみた

Tailwind CSSはユーティリティファーストのCSSフレームワークです。Tailwind CSSの特徴は、「1つのクラス名は1つのstyleに対応する」です。例えばmx-autoは「マージンの横方向をautoにする」というものです。

そして、Bootstrapとの違いは「button」のようなコンポーネントが存在しないことです。Tailwind CSSは、ユーティリティとして提供されるクラスを組み合わせてコンポーネントを作り上げるのです。

関連記事

Tailwind CSSと他のCSSフレームワークを分ける最大の特徴は、Tailwind CSSで作られたサイトにはいわゆる「bootstrap臭」を感じないところです。CSSの組み合わせ方は人によって異なるため、同じようなデザインにはならないからです。

Webサイトを手軽に作りたい。けれども、CSSを書くのは煩雑で苦手だと感じる方は少なくないと思います。

本記事ではTailwind CSSの特徴を紹介した後、私が製作したサイトのパーツをサンプルとして、Tailwind CSSを使えばCSSを書くことなくデザインを実装できることを解説していきたいと思います。

Tailwind CSSの特徴

Tailwind CSSの特徴をいくつか紹介します。

・ CSSを当てるためのクラス名が揃っている
・ 値の追加や上書き、削除などカスタマイズが可能
・ 共通箇所と、差異のある箇所を適切に切り出せる
・ 何も考えずにレスポンシブ対応が可能

1つずつ詳しく見ていきましょう。

CSSを当てるためのクラス名が揃っている

多くのCSSフレームワークは、クラス名を当てることでCSSを記述せずにスタイルを整えることができます。Tailwind CSSも同様の機能を持っています。

例えば、個人開発で作ったCreepy Nutsのファンサイトのボタンは下記のようなクラス名を当てています。

黒くて丸いトップに戻るボタン

<a class="bg-black text-white font-bold py-5 px-10 rounded-full shadow-xl hover:bg-gray-dark hover:text-white">
  <span class="text-lg font-light">トップに戻る</span>
</a>

クラス名を読むだけでもパーツの特徴が伝わってきますね。aタグのクラス名とCSSプロパティと値は以下のように対応しています。

.bg-black { background-color: #1b1c1d; }
.text-white { color: #fff; }
.font-bold { font-weight: 700; }
.py-5 {
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
}
.px-10 {
  padding-right: 2.5rem;
  padding-left: 2.5rem;
}
.rounded-full { border-radius: 9999px; }
.shadow-xl { box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); }

クラス名はプロパティと値を短縮した名前なので、単にCSSを書くよりも記述量を削減できます。

また、それぞれのクラス名と対応する値は公式ドキュメントに掲載されています。興味のある方は、一例としてpaddingを見てみてください。

値の追加や上書き、削除などカスタマイズが可能

Tailwind CSSはカスタマイズが柔軟に行えるので、元々設定されていない値を追加することもできます。例えば、paddingならp-2padding: 0.5remp-3padding: 0.75remというように、あらかじめ値を設定してくれています。

しかし、paddingのクラス名はp-64が最大です。つまり、padding: 16remが組み込みのpaddingの上限です。一方、実務ではより大きなpaddingを必要とする場面があるでしょう。

そのような時には、tailwind.config.jsをカスタマイズしてクラス名を自由に追加できます。

tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        '14': '3.5rem',
        '72': '18rem',
        '84': '21rem',
        '96': '23rem',
      },
    },
  },
}

これで、p-14, p-72, p-84, p-96が使えるようになりました。Tailwind CSSはPostCSSで書かれており、JavaScriptで設定を記述できるので、このように柔軟なカスタマイズが可能になります。これがTailwind CSSの大きな特徴といえます。

また、値の上書きも可能です。先ほどのボタンを作るに当たり、私はデフォルトの黒色を変更しています。

tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        black: {
          default: '#1b1c1d',
        },
      },
      spacing: {
      // ...
      },
    },
  },
}

これにより、bg-blacktext-blackなどのクラス名で当たる色が#1b1c1dに上書きできます。

元々bg-blackの色の指定は#000000です。但し、この色をそのまま使うとキツい印象を与えてしまうため、深い青である#1b1c1dを使ってキレのある黒を表現しています。

黒くて丸いトップに戻るボタン

クラス名と色の対応はTailwind CSSのカラーパレットに掲載されています。ぜひ一度ご覧になることをお勧めします。どの色も美しく、眺めているだけでも色に対する感覚が養われること間違いなしです。

コンポーネント単位のクラス名はない

Tailwind CSSにはbtncardといったクラス名は存在しません。作者Adam Wathan氏は自身のブログでその理由を詳細に説明しています。

HTMLとCSSの関係について実践的でロジカルな彼の探求の成果をぜひ一読して頂きたいのですが、時間のない読者の方のために端的に説明すると記事の主張は「CSSでも継承よりコンポジションを好む」ことだと私は読み取りました。

つまり、「.btnを継承する.btn—primaryや.btn—secondaryを作るのではなく、クラス名を1つ1つ組み合わせてコンポーネントを作る」方が複雑なコンポーネントを作るときもシンプルに管理できることです。

これが、Tailwind CSSがユーティリティファースト(utility-first)であると標榜する理由なのです。ユーティリティファーストという言葉は、公式ドキュメントのトップページで使われており、Tailwind CSSを特徴付ける考え方と言えるでしょう。

A utility-first CSS framework for rapidly building custom designs.

しかし、自分で一からボタンやカードといった基本的なコンポーネントを作る必要はありません。ドキュメント内にボタンやカード、フォームといったWebサイトでよく使われるコンポーネントのサンプルがあるからです。このコンポーネント群を基礎にして、自分なりのアレンジを加えていきましょう。

(ちなみに、コンポーネントのみならずページ単位のテンプレートが利用できるTailwind UIというサービスもあります。こちらは現在有料で利用者を募集しています)

小さいものを組み合わせるという考え方は、UNIXの「Small is beautiful」という設計思想にも通じるところがあります。

小さなプログラムは、単独では大したことはできない。ほん1つか二つの機能を実行するだけだ。しかし、それらを様々に組み合わせることで、真のパワーを発揮する。部分の総和は全体よりも大きくなり、大きくて複雑な作業も簡単に処理できる。 UNIXという考え方―その設計思想と哲学

「プログラム」を「クラス」に、「作業」を「パーツ(コンポーネント)」と読み替えると、まるでTailwind CSSについて語っているように思えますね。

何も考えずにレスポンシブ対応が可能

レスポンシブ対応に、いつも頭を悩まされる人は多いと思います。ブレイクポイントをいくつ設定するのか、それは何ピクセルなのか。Media Queryを書くのも面倒ですよね。

Tailwind CSSはこの煩雑さを解決してくれます。下記のブレイクポイントを設定してくれているからです。

/* Small (sm) */
@media (min-width: 640px) { /* ... */ }

/* Medium (md) */
@media (min-width: 768px) { /* ... */ }

/* Large (lg) */
@media (min-width: 1024px) { /* ... */ }

/* Extra Large (xl) */
@media (min-width: 1280px) { /* ... */ }

私は個人開発でサイトを作る際は、ブレイクポイントをmdの一点にし、スマホ・タブレットとPCで分けています。

ヘッダーは下記のように書いています。

<div className="h-16 flex items-center md:max-w-screen-md md:mx-auto">...</div>

これはmax-w-screen-md mx-autoはmd以上の幅でスタイルが当たるということを示しています。

サイトのヘッダー

レスポンシブ対応はサイトのレイアウトやパーツのデザインと密接に関連しているので、そもそもデザインがまずい場合はまずデザインを見直す必要があります(Googleに「レスポンシブ ウェブデザイン パターン」という記事があり、レスポンシブデザインを考えるのにお勧めです)。少なくともエンジニアがレスポンシブ対応のためにCSSを学ばなければならないコストは格段に下がります。

(ちなみに、サイトのロゴの箇所に栗とナッツを配置しているのは、この絵文字がCreepy Nutsの愛称だからです。彼らのダサカッコ良さを表現するのに最適だと考えて配置しているのですが、一般の方からすると単にダサく思えますよね。ファンからは好評なのですが…。)

コメントとカードのパーツをご紹介します

では、実際にイケてるパーツを簡単に作れるということを、引き続き私が個人開発で製作したサイト(Creepy Nutsファンサイト)を例に説明していきます。

コードはReactですが、HTMLさえ知っていればReactの知識がなくても読み進められます。

カードのコンポーネント

CDを紹介するカードコンポーネント

VerticalCard.tsx
const VerticalCard: React.FC<Props> = ({ title, englishTitle, imageUrl, releasedAt }) => (
  <Link href={DISCOGRAPHY_ID_PATH} as={`${DISCOGRAPHY_PATH}/${englishTitle}`}>
    <a className="vertical-card">
      <img src={imageUrl} alt={title} width={150} height={150} />
      <div className="p-4 text-center">
        <p className="mb-2 text-gray-darkest">{title}</p>
        <p className="text-gray-dark">
          <span>{releasedAt}</span>
        </p>
      </div>
    </a>
  </Link>
)

上記、クラス名を解説していきます。aタグにvertical-cardというクラス名がありますね。先ほど「btnやcard」というクラス名はTailwind CSSに存在しないと書きましたが、どういうことでしょう。一旦スキップして後ほど解説します。

divタグはp-4text-centerを当てています。これでdiv内のテキストが中央揃えになります。

pタグではmargin-bottomで余白を確保したり、text-gray-darktext-gray-darkestで色の濃さを指定しています。

さて、vertical-cardです。これは自分で設定したクラス名です。scssを見てみましょう。

.vertical-card {
  max-width: 150px;
  @apply bg-white rounded-lg overflow-hidden shadow-xl mx-auto my-6;
}

@applyディレクティブを使うことで、Tailwind CSSのクラス名を自分が設定したクラスの中で利用できます。max-widthをインラインで書くことを避けたかったため、vertical-cardという名前をつけて切り出したのです。

ちなみに、Creepy Nutsファンサイトの中でこのようにCSSを書いている箇所は他に3箇所しかありません。

私は仕事でCSSを書かないエンジニアです。しかし、この開発体験の良さからTailwind CSSの汎用性の高さを思い知り、同じ境遇のエンジニアの武器になると確信しています。

コメントのコンポーネント

次に、コメントのコンポーネントを紹介します。

動画に対するコメント

Comment.jsx
const Comment: React.FC<Props> = ({ comment, formattedCreatedAt, liked, handleClick }) => (
  <div className="py-4" key={comment.id}>
    <p className="flex justify-between py-4 px-6">
      <span className="text-gray-dark">{formattedCreatedAt}</span>
      <span className="text-gray-dark">{comment.username}</span>
    </p>
    <div className="mx-4 relative rounded-lg shadow-lg">
      <span className="comment-left-top-icon text-4xl">{comment.emoji}</span>
      <p className="px-10 pt-10 py-6 text-gray-darkest leading-relaxed">{comment.body}</p>
      <p className="pb-4 flex justify-end">
        <button className="focus:outline-none" type="button" onClick={handleClick}>
          <span className="pr-2 text-xl">
            {liked ? <Icon className="text-orange" name="thumbs up" /> : <Icon color="grey" name="thumbs up" />}
          </span>
        </button>
        <span className="pr-10 text-lg text-gray">{comment.likeCount}</span>
      </p>
    </div>
  </div>
)

Like機能のbuttonタグにfocus:outline-noneというクラス名があります。これはその名の通り、focusが発生すれば、擬似クラス(focus:)に付与したプロパティを有効にするということです。ここでは、outlineがなくなるということですね。

公式ドキュメントには他にもhoverやactiveといった擬似クラスが紹介されています。

なお、コメントの左上で栗やナッツを表示している.comment-left-top-iconは自分でCSSを書いています。

/* コメントの左上の栗かピーナッツのアイコン */
.comment-left-top-icon {
  position: absolute;
  left: -12px;
  top: 4px;
  text-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
}

Tailwind CSSのメリットとデメリット

私が小〜中規模のサイトを作った手応えを紹介していきます。これは非デザイナーである個人開発者の感想なので、絶対的なメリット・デメリットではありません。

メリット

・ 誰でもLook and Feelが良いサイトが作れる
・ デザインの統一感が出せる
・ 「Tailwind CSS」を使っていることをユーザーが意識しない
・ CSSサイズ肥大化によるパフォーマンス低下を避けられる

「誰でも見た目がいいサイトが作れる」というところは、私が一番気に入っているDJ松永のプロフィールページを紹介させてください。一度ページをご覧いただきたいのですが、このページは友人にもカッコいいと好評でした。

DJ松永のプロフィールページ

Tailwind CSSを使っていて、誰でも感じのいいサイトを作れる威力を感じたポイントでした。

また、Tailwind CSSのUtilityの中からクラス名を選んでCSSを当てていくので、デザインが統一されているという印象を与えることができます。

この特徴は公式ドキュメントの「Tailwind CSSはデザインシステムを作るためのエンジンである」という言葉にも表れています。

Tailwind is more than a CSS framework, it’s an engine for creating design systems. (Designed to be customized

そして、bootstrapを使っているサイトは「bootstrap臭がする」と揶揄されたり、Material UI製のサイトは「Googleのツールのようだ」と言われるのとは異なり、クラス名を覗かない限りTailwind CSSではTailwindを使っていることがわかってしまうということもないでしょう。コンポーネントはUtilityの組み合わせであるからです。

最後に、Tailwind CSSにはPurgeCSSが組み込まれています(version 1.4から。それまではpostcss.config.jsに正規表現の記述をする必要があった)。Productionでのビルド時にはViewファイルで使われているクラス名だけを抽出するため、不要なスタイルをCSSにコンパイルしません。

このため、CSSのサイズを無闇に肥大化させず、CSSの読み込み速度の低下を免れるでしょう。PurgeCSSの恩恵はhtmlでもvueでもJSXでも簡単に受けることができます。

(なお、上記サイトはNext.jsで作っているので、私のtailwind.config.cssのpurgeの箇所は下記のように記載しています)

tailwind.config.css
module.exports = {
  purge: ['./src/Components/**/*.tsx', './pages/**/*.tsx'],
  // ...
}

これらのメリットを考慮するとTailwind CSSは、他のCSSフレームワークと比べてかなり筋がいいと考えています。

そして、何より公式が動画教材を用意してくれていいます。その英語が聞き取りやすく、またTailwind CSSの機能を一通りカバーしていることもメリット1つです。

デメリット

・ Semantic UIやMaterial UIと組み合わせが悪い

デメリットとしては、Semantic UIやMaterial UIのようなコンポーネントが構築済みのツールとの相性がよくないことです。実際にSemantic UIのコンポーネントにTailwind CSSのクラス名を当ててみたところ、DOMの階層の関係でスタイルが当たらなかったことがありました。

滅多にないケースだと思いますが、以前「Tailwind CSSとMaterial UIを組み合わせてシステムを作りたい」という相談を受けました。食い合わせが悪いことを説明して納得してもらうことができたのですが、そのように考える人も少なくないのだろうと思い、デメリットとして挙げておきます。

想定されるユースケース

Tailwind CSSのユースケースとして最適なのは、個人開発やデザイナーがいないスタートアップや新規プロジェクトでしょう。

CSSが苦手なエンジニアでもいいデザインが作れるため、デザイナーのリソースがない場合に開発の追い風となってくれます(Tailwindは追い風の意味)。

CSSを管理する手間が省けることは、エンジニアにとってはとても楽です。BEMでは、自分でBlock, Element, Modifierの名前を考える必要がありますが、命名における脳のリソース消費量は侮れません。

Tailwind CSSでは基本的に命名をしないので、瑣末になりがちなModifierの命名に頭を悩ませることもなく、レビューを受けてクラス名を変更する手間もありません。エンジニアが思考停止でスタイルを当てられる恩恵は少なくないでしょう。我々エンジニアは脳のリソースをサーバーサイドやフロントエンドのプログラムのクリーンな設計に費やしましょう。

新規開発で導入することがベストですが、もし既存のプロジェクトにTailwind CSSを追加するなら、既存のクラスのプロパティを分解して、tailwind.config.jsに1つずつプロパティを追加していくことから始めることをお勧めします。「小さいプログラムを組み合わせる」UNIXの発想ですね。これがTailwind CSSのベストプラクティスです。

まとめ

いかがでしたでしょうか。Tailwind CSSの利点、思想、使い方を紹介してきました。

開発者のAdam氏のブログ記事では「継承よりコンポジション」「関心の分離」というフレーズが何度も登場します。彼はフルスタックのエンジニアであり、プログラミングの原理原則をCSSに適用する方法を考え抜いているという印象を受けました。

また、「共通のクラス」を抽出するタイミングは、繰り返しが生じたときだと記事中で説明されています。これは「早すぎる抽象化を避ける」という原則にも通じます。Adam氏が一流のプログラマであることの証左ですね。

ちなみに、彼はLaravelの開発者のTaylor氏とも友人で、Tailwind CSSでLaravel Vaporの美しいサイトを作成しています。「会社で導入を説得するためにプロダクションで使われている事例が欲しい」のであれば、このサイトを紹介してみましょう。

Laravel Vapor トップページ

さて、Tailwind CSSはCSSを当てるための1つの手段であり、あくまで素晴らしいデザインをシンプルに実現し、スタイルの管理を追求するためのツールです。その成果はサイトをデザインするデザイナー、そして実装するエンジニアの手に掛かっています。

Tailwind CSSという追い風を受けて、スタイル管理の沼に足を取られず進んでいきましょう。それでは、Bon Voyage!

Happy Coding 🎉