Tailwind CSSはダメなのか？

# 初めに

この記事ではTailwind CSSの書き方について、思うがままに書かせていただきました。

個人的見解が多分に含まれる内容となっています。

Tailwindが好きな人間なので、普通のCSSやSassを過小評価してる部分はあると思いますが、ご了承いただけたら幸いです。

# Tailwindがダメと言われる理由

ちょっと前にTailwindがどうだとかいう論争が起きてましたね。

私は趣味に没頭していたので、その時はあらゆる投稿に対していいねを押すマシーンと化してました。

中でも「Tailwindは負債になる」とか「Tailwindは不要」とか、デメリットを指摘する投稿が多かった印象を受けます。

――そもそもTailwindは何が悪いのでしょうか？本当に悪いんでしょうか？

以下に、私が見かけた「Tailwindがダメ」と言われる理由を列挙します。

```markdown
- クラスが大量に書かれて見づらい
- 可読性が悪い
- 覚えること多くて大変
- HTMLにCSSを持ち込むべきではない（関心の分離）
- 可読性が悪い
- なんか気に食わない
- 可読性が悪い
- styled-components最高！！！
- 可読性が悪い
- 可読...
```

そのほとんどは、可読性の悪さを指摘されていました。

まぁ、確かにCSSの代わりにTailwind書いたらそりゃ可読性悪くなるのは必然だと思います。

Tailwindはある種、Component指向に寄り添った代物だと思っているので、CSSの代わりに書いたらそりゃ読みにくくなると思います。

Component指向を行ったうえで扱うものだと思っています。

また、Tailwindと比較してあげられるのがstyled-componentsです。

CSS-in-JS界隈ではTailwindよりもstyled-componentのほうが良いじゃないか？と言われてる印象があります。

私個人としては「どっちでもいい」と思っているのですが、

それでも、どちらが良いかを選ばなければいけない立場なら、Tailwindに軍配が上がると思っています。

何故そう思うのか、サンプルを見ながら確認していきます。

# これは見にくい

まず、べた書きで書いたReact + Tailwindを見ていきます。

React + Tailwindを使った見にくい例です。を見ていきます。

```tsx
import React from "react";

const Index = () => {
  return (
    <div className="flex items-center justify-center h-screen bg-gray-100">
      <div className="w-[400px] h-[300px] flex flex-col justify-center px-4 mx-auto bg-white rounded-lg shadow-md dark:bg-gray-800">
        <h1 className="mb-4 text-xl font-semibold text-gray-700 dark:text-gray-200">
          Tailwind好きです
        </h1>
        <p className="mb-4 text-gray-600 dark:text-gray-400">好きな理由は……</p>
        <button className="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-500">
          こちらをクリック！
        </button>
      </div>
    </div>
  );
};

export default Index;
```

……見にくい。

正直、初見で「これって何してるの？」って聞かれたら、一発で答えられる自信は無いです。

なるほど。

確かにこういったサンプルを見せられると「Tailwind終わってんな」って思っちゃいますよね。

HTML/CSSでは意味付け（セマンティックに書く）を重要視しているため、これをスタイリングすると「パッと見て分かるように書かれる」ことが多いです。

なので、HTML/CSSにおいて、Tailwindを使うという選択肢は正直ないと思っています。

だって、ただ見にくくなるからです。

じゃあ、Reactにおいては？

ひと先ず、CSSで書く方法見ていきましょう。

Reactでは、CSSを書くときmodule.cssで書きます。

## module.cssで書く

次のようになります。

```tsx
/* styles.module.css */
.container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background-color: #f7fafc;
}

.card {
  width: 400px;
  height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 16px;
  margin: auto;
  background-color: white;
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.23);
}

@media (prefers-color-scheme: dark) {
  .card {
    background-color: #2d3748;
  }
}

.title {
  margin-bottom: 16px;
  font-size: 1.25rem;
  font-weight: 600;
  color: #4a5568;
}

@media (prefers-color-scheme: dark) {
  .title {
    color: #edf2f7;
  }
}

.text {
  margin-bottom: 16px;
  color: #718096;
}

@media (prefers-color-scheme: dark) {
  .text {
    color: #a0aec0;
  }
}

.button {
  padding: 8px 16px;
  font-size: 0.875rem;
  font-weight: 500;
  color: white;
  background-color: #3182ce;
  border-radius: 0.5rem;
  transition: background-color 0.2s;
}

.button:hover {
  background-color: #4299e1;
}

/** App.jsx */
import React from "react";
import styles from './styles.module.css';

const Index = () => {
  return (
    <div className={styles.container}>
      <div className={styles.card}>
        <h1 className={styles.title}>
          Tailwind好きです
        </h1>
        <p className={styles.text}>好きな理由は……</p>
        <button className={styles.button}>
          こちらをクリック！
        </button>
      </div>
    </div>
  );
};

export default Index;
```

JSX側は見やすくなりました。

だけど、CSS側が長くて、正直管理しにくいです。

次に、Tailwindを使った修正を見ていきます。

## コンポーネント分割

上記の例の見にくさの理由は何でしょうか？

適切なコンポーネントに分割していないからだと思います。

現代ではコンポーネント指向が主流で、適切なコンポーネントに分割することが何よりも可読性を高めます。

```tsx
const Card = ({ children }) => (
  <div className="w-[400px] h-[300px] flex flex-col justify-center px-4 mx-auto bg-white rounded-lg shadow-md dark:bg-gray-800">
    {children}
  </div>
);

const Title = ({ children }) => (
  <h1 className="mb-4 text-xl font-semibold text-gray-700 dark:text-gray-200">
    {children}
  </h1>
);

const Text = ({ children }) => (
  <p
    className="mb-4 text-gray-600 dark:text-gray-400"
  >
    {children}
  </p>
);

const Button = ({ children }) => (
  <button
    className="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-500"
  >
    {children}
  </button>
);
```

必要なコンポーネントを抜き出しました。

これで先ほどのトップレベルの部分を見ますと、

```tsx
const Index = () => {
  return (
    <div className="flex items-center justify-center h-screen bg-gray-100">
      <Card>
        <Title>Welcome to Tailwind CSS!</Title>
        <Text>Lorem ipsum dolor sit amet...</Text>
        <Button>Click me</Button>
      </Card>
    </div>
  );
};
```

滅茶苦茶見やすくなったと思います。

これで十分だと思います。

ん？

「module.css +コンポーネント分割で良くない？」

確かに可読性においては、そうかもしれません。

ただ、私個人としては可読性だけではなく「ファイル管理」というのも保守しやすさの一つだと考えています。

わざわざmodule.cssのファイルを増やしてまでCSSを書くメリットってあるんでしょうか？

私は正直ないかなーと思っています。

そういったこともあり、CSSを書くか、CSS-in-JSで一つのファイルで済ませるのか。

また、CSSを書くようなシステムは「セマンティック」を考える意味合いも増えてしまいます。

コンポーネントに分割したのに、さらにそこに細かな意味を見出しては名前付けしなければいけません。

それって滅茶苦茶大変な作業じゃないでしょうか。

そうなるとやはりCSS-in-JSで、「Tailwind」「styled-componets」をかのどちらかを利用したいと考えるようになります。

よし、これで十分ですね……

と、行きたいところなんですが、これではTailwindとstyled-componentsの差があまり良く分かりません。

なので、もう少し発展していきます。






## 横に長くなる問題をどうするか

Cardコンポーネントを見てみます。

```tsx
const Card = ({ children }) => (
  <div className="w-[400px] h-[300px] flex flex-col justify-center px-4 mx-auto bg-white rounded-lg shadow-md dark:bg-gray-800">
    {children}
  </div>
);
```

横に長すぎますね。

これを見て、styled-componentの、いい例を次のように上げられることが多いです。

```tsx
import styled from 'styled-components';

const Card = styled.div`
  width: 400px;
  height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 16px;
  margin: auto;
  background: white;
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.23);
  @media (prefers-color-scheme: dark) {
    background: #1a202c;
  }
`;
```

縦に並べられて見やすいですね！

でも、これって本当にstyled-componentsだけの良さなのでしょうか？

Tailwindでも同様な可読性を求められないか、試してみましょう。

次のように修正してみます。

```tsx
const Card = ({ children }) => (
  <div
    className={`
        w-[400px] h-[300px]  
        px-4 mx-auto
        flex flex-col justify-center
        bg-white dark:bg-gray-800
        rounded-lg shadow-md
    `}
  >
    {children}
  </div>
);
```

JSではテンプレートリテラルという構文で、上記のように改行することが可能です。

パッと見、どっちが見やすいですか？

もう一度、styled-componentsを出しましょう。

```tsx
import styled from 'styled-components';

const Card = styled.div`
  width: 400px;
  height: 300px;
  padding: 16px;
  margin: auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: white;
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.23);
  @media (prefers-color-scheme: dark) {
    background: #1a202c;
  }
`;
```

Tailwindに慣れてるからかもしれないのですが、私はTailwindの方が見やすいです。

何故こんな現象が起きるのかというと、単純に「文字数の差」です。

例えば横幅400pxを指定する場合、

width: 400px → 11文字

w-[400px] → 9文字

background: white → 15文字

bg-white → 8文字

こういった文字数の差が積み重なることで、styled-componentsよりもTailwindのほうが見やすくなってるように私は感じます。

# まとめ

ここまでTailwind好きが、色々と述べてきました。

見てくれてありがとうございます。

まとめると、

- CSS(module css)
    - ファイルが増えてめんどくさい
    - セマンティックがめんどくさい
- styled-components
    - 文字数多い
- Tailwind
    - コンポーネント化と改行さえ気を付ければ見やすい

こんな感じです。

もちろん、Tailwindにも弱点はあります。

ですが、可読性という観点では、私の中では一番いいと思えます。

皆さんはどうでしょうか？