🙆‍♀️

Tailwind CSSは本当にダメなのか

2023/07/22に公開

初めに

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

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

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

Tailwindがダメと言われる理由

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

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

中でも「Tailwindは負債になる」とか「Tailwindは不要」とか、デメリットが多い印象を受けましたね。

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

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

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

結局のところ、可読性の悪さを指摘されることが物凄く多いように感じます。

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

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

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

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

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

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

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

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

これは見にくい

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

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

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では意味付け(セマンティックに書く)をするため、パッと分かるよう書くのが良しとされています。

例えばBEMとかだと、CSSが数個で済むようになるかと思います。

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

module.cssで書きます。

module.cssで書く

連続して書きます。

/* 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 + コンポーネント分割で、次のようにしてみます。

コンポーネント分割

上記の例の見にくさの理由は適切なコンポーネントに分割していないからです。

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

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>
);

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

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

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を書くメリットってあるんでしょうか?

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

そういったこともあり、一つのファイルで済む「Tailwind」または「styled-componets」のどちらかを利用したいと考えています。

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

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

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

やはりCSS-in-JSでTailwindまたはstyled-componentsが良さそうです。

これで十分ですね……

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

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

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

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

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の、いい例を次のように上げられることが多いです。

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でも同様な可読性を求められないか、試してみましょう。

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

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を出しましょう。

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にも弱点はあります。

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

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

Discussion