この記事はこういう方にオススメ

Tailwind CSSでスタイリングしていて大量のクラスの羅列に「ウッ!」となったことのある方

Tailwind CSS、便利ですね。初めて目にしたときには多大なカルチャーショックを受けたものですが、 HTMLから離れずにスタイリングができる 点、 CSSファイルが荒れない 点はとても便利だなあと感じます。

独特のクラス名も覚えてきてサクサクスタイリングができるようになってきたなぁ……という今日この頃なのですが、同じクラスのツブツブ達を色んな画面にペタペタとコピペしていて思いました。

<button class="rounded-full bg-gradient-to-tr from-orange-300 to-red-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all">
</button>

長い!読みにくい!! これ、まとめられへんのか!?」と。

@applyとの出会い

まとめられるらしい

@apply を使うと、まとめられるらしい。やってみよ。

お題にこんなボタンを作ってみました。

<div class="mb-10 flex flex-row items-start gap-10"> <button class="rounded-full bg-gradient-to-tr from-orange-300 to-red-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-green-300 to-blue-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-lime-300 to-teal-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-gray-300 to-gray-200 px-6 py-2 text-base font-bold text-white" disable> </button> <div class="flex flex-row items-start gap-10"> <button class="rounded-lg bg-gradient-to-tr from-orange-300 to-red-600 px-4 py-2 text-xs font-medium text-white drop-shadow-sm hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-green-300 to-blue-600 px-4 py-2 text-xs text-white hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-lime-300 to-teal-600 px-4 py-2 text-xs text-white hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-gray-300 to-gray-200 px-4 py-2 text-xs text-white" disable> </button> <div class="mb-10 flex flex-row items-start gap-10"> <button class="rounded-full bg-gradient-to-tr from-orange-300 to-red-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-green-300 to-blue-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-lime-300 to-teal-600 px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all" </button> <button class="rounded-full bg-gradient-to-tr from-gray-300 to-gray-200 px-6 py-2 text-base font-bold text-white" disable> </button> <div class="flex flex-row items-start gap-10"> <button class="rounded-lg bg-gradient-to-tr from-orange-300 to-red-600 px-4 py-2 text-xs font-medium text-white drop-shadow-sm hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-green-300 to-blue-600 px-4 py-2 text-xs text-white hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-lime-300 to-teal-600 px-4 py-2 text-xs text-white hover:opacity-80 hover:transition-all" </button> <button class="rounded-md bg-gradient-to-tr from-gray-300 to-gray-200 px-4 py-2 text-xs text-white" disable> </button>

共通化を考えていく

スタイルに規則性があるので、共通化できるクラスのグルーピングを考えていきます。コンポーネントとしての「ボタン」と、パターンとしての「カラー」は分けて考えることができそうです。

まずはボタンの基礎部分を大・小でまとめていきます。形状やホバー効果、テキストカラーの白はボタン共通として良さそうです。 @layer は、ボタンはコンポーネントであると言えるので components にします。

@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
  .btn-big {
    @apply rounded-full  px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all;
  .btn-small {
    @apply rounded-lg px-4 py-2 text-xs font-medium text-white drop-shadow-sm hover:opacity-80 hover:transition-all;

@applyしてできたクラスを適用するとこんな感じ。この時点でもかなりスッキリしました。

<!-- おおきいボタン -->
<button class="btn-big bg-gradient-to-tr from-orange-300 to-red-600">
</button>
<!-- ちいさいボタン -->
<button class="btn-small bg-gradient-to-tr from-orange-300 to-red-600">
</button>
@layer components { .btn-big { @apply rounded-full px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all; .btn-big-disable { /* 追加 */ @apply rounded-full bg-gradient-to-tr from-gray-300 to-gray-200 px-6 py-2 text-base font-bold text-white; .btn-small { @apply rounded-lg px-4 py-2 text-xs font-medium text-white drop-shadow-sm hover:opacity-80 hover:transition-all; .btn-small-disable { /* 追加 */ @apply rounded-md bg-gradient-to-tr from-gray-300 to-gray-200 px-4 py-2 text-xs text-white; @layer components { .btn-big { @apply rounded-full px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all; .btn-big-disable { @apply rounded-full bg-gradient-to-tr from-gray-300 to-gray-200 px-6 py-2 text-base font-bold text-white; .btn-small { @apply rounded-lg px-4 py-2 text-xs font-medium text-white drop-shadow-sm hover:opacity-80 hover:transition-all; .btn-small-disable { @apply rounded-md bg-gradient-to-tr from-gray-300 to-gray-200 px-4 py-2 text-xs text-white; @layer utilities { .red { @apply bg-gradient-to-tr from-orange-300 to-red-600; .blue { @apply bg-gradient-to-tr from-green-300 to-blue-600; .green { @apply bg-gradient-to-tr from-lime-300 to-teal-600;
<div class="p-10">
  <div class="mb-10 flex flex-row items-start gap-10">
    <button class="btn-big red">ボタン大</button>
    <button class="btn-big blue">ボタン大</button>
    <button class="btn-big green">ボタン大</button>
    <button class="btn-big-disable" disable>非活性</button>
  <div class="flex flex-row items-start gap-10">
    <button class="btn-small red">ボタン小</button>
    <button class="btn-small blue">ボタン小</button>
    <button class="btn-small green">ボタン小</button>
    <button class="btn-small-disable" disable>非活性</button>

めちゃくちゃスッキリ!!!

ん? でも待てよ…?

でもこれって、当初Tailwind CSSに感じていた素晴らしさHTMLから離れずにスタイリングができる」「CSSファイルが荒れないに反しているんじゃないでしょうか……?

結局、昔とやっていることが同じじゃない?

コンポーネント指向とTailwind CSS

コンポーネント指向と相性がいいTailwind CSS

Tailwind CSSは、ReactやVue.jsといったフロントエンドのフレームワークの考え方「コンポーネント指向」と相性が良いのです。今回の話題で言うと、コンポーネントの外から中身のコードを気にする必要がなくなる点がGoodです。

なので、たとえばReactであれば・・・

こんな感じのコンポーネントを作って

type ButtonBigProps = {
  caption: string
  color: color
  disabled: boolean
const color = {
  red: 'bg-gradient-to-tr from-orange-300 to-red-600',
  blue: 'bg-gradient-to-tr from-green-300 to-blue-600',
  green: 'bg-gradient-to-tr from-lime-300 to-teal-600',
} as const
type color = typeof color[keyof typeof color]
const ButtonBig: React.FC<ButtonBigProps> = ({ caption, color, disabled }) => {
  if (disabled) {
    return (
      <button
        className='rounded-full bg-gradient-to-tr from-gray-300 to-gray-200 px-6 py-2 text-base font-bold text-white'
        disabled>
        {caption}
      </button>
  } else {
    return (
      <button
        className={`${color} rounded-full  px-6 py-2 text-base font-bold text-white drop-shadow-lg hover:scale-95 hover:opacity-70 hover:transition-all`}>
        {caption}
      </button>