LoginSignup
120
51

More than 1 year has passed since last update.

TailwindCSSは複雑性を足すだけで、何もしていない(和訳)

Last updated at Posted at 2021-06-21

釣り針のクソデカいタイトルですが、こちらの記事はロンドンのフルスタックNode/JS/TS開発者のBrian Boykoさんが4月20日にDEV Communityに投稿した記事:TailwindCSS: Adds complexity, does nothing.の和訳となります。(6/28原文著者の掲載許可取得済み)
こちらの記事を5月7日にtwitterで10万人のフォロワーを持つフロントエンド開発者でインフルエンサーのSara Soueidanさんがリツイートし、それにTailwindCSSの作者 Adam Wathanさんが反応したことで炎上。議論を巻き起こした様です。(こちらの炎上事件の詳細は: Tailwind CSS批判ブログ記事の紹介ツイートへの攻撃で作者が炎上 などでご確認ください)
さてさて、日本ではフロントエンドのオピニオンリーダー的な影響力の強いエンジニアにも概ね好意的に受け入れられ、破竹の勢いといってもいいTailwindCSSですが、海外ではポツポツこちらの記事のような批判も強まってきているようです。建設的批判という言葉がありますが、技術選定の際に、肯定的な意見と同じくらい批判的な意見もしばしば役に立ちます。ProsとConsの両方を知っておくことで、ある技術がプロジェクトにとって最適なものかどうか判断する材料になるでしょう。
前置きは以上で、以下が記事の和訳となります。


TailwindCSS: 複雑性を足すだけで、何もしていない

フロントエンドの仕事をしている人なら、BootstrapのようなCSSライブラリであるTailwindCSSについてよく耳にすると思います。しかしながら、TailwindはBootstrapとは大きく異なるアプローチをとっており、それはすべてが「ユーティリティクラス」であるということです。

そして私はこのライブラリのファンではありません。私はそれの匂いを少し嗅いで、すぐにその名前がよく名付けられたものだと学びました。それはオナラと同じくらい歓迎される役に立つものでした。(*訳註 Tailwind=追い風 に対する皮肉

始める前に、ユーティリティクラスとは何かを説明してみましょう。例えば、多くのコンポーネントがあり、そのうちの多くのコンポーネントがCSSのスタイルプロパティ "display: flex; "を必要としているとき、これを何度も何度もCSSに記述する代わりに、"flex "というクラスを作成します。

.flex {
  display: flex;
}

そして、flexを必要とするすべてのコンポーネントに、その「flex」クラスを追加します。
これは悪いことではありません。特にCSS-in-JSソリューションやSass/SCSSのようなプリプロセッサの助けを借りずにCSSを書いているときには、私自身もユーティリティクラスを書いてよく使っています。
Tailwindはそのコンセプトを極限まで高めたもので、CSSを書く必要はほとんどなく、適用する必要のあるスタイルに応じて異なるクラスを書けばよいというものです。これは興味深い選択ですね...


(えっ、でもこれってただの、段階を踏んだインラインスタイルみたいに聞こえるよ…)

これはただの段階を踏んだインラインスタイルです

それだけです。<div class="flex">foo</div>の記述は、<div style="display: flex;">foo</div>の記述とまったく同じ効果があります。まあ、インラインスタイルがクラスよりも優先度が高いという点で若干の違いはありますが、それはこの文脈ではあまり関係ありません。

つまり、CSSの優先順位を除いて、あなたのコードベースでインラインスタイルを使うことに反対する議論と同じことがTailwindを使うときにも当てはまります。
例えば、Lifewire:CSSデザインの為にインラインスタイルを避けるや、StackOverflow:インラインCSSの何がそんなに悪いの?や、あなたがプロダクションReactアプリでインラインスタイルを使わないでいるべき理由などです。
Tailwindのどこが悪いのかを説明するために、他のユーザーのインラインスタイル批判を蒸し返すのはちょっと怠慢な気がしますが、実際に1対1のマッピングなのです。インラインスタイルに余分なステップを加えただけなのです。

Tailwindがインラインスタイルと共有している問題のいくつかを紹介します。

It's WET, not DRY.(TailwindはDRYではない)

サイトのスタイルを大幅に変更する場合、ユーティリティークラスを使用している場合は、ユーティリティークラスの各用途、つまりすべてのコンポーネントを確認し、何を更新する必要があるかを視覚的に判断する必要があります。例えば、あなたの会社のプライマリーカラーが青だったとしましょう。あなたのウェブサイトにはたくさんの青いものがあり、'text-blue-500'や'bg-blue-300'といったマークを付けて、青の濃さを変えています。それはいいのですが、会社のブランドを変更することになり、サイト上のすべてのボタン(ただしボタンだけ)を赤にする必要が出てきました。

この場合、各コンポーネントを調べて、'text-blue-500'を'text-red-500'に手動で変更しなければなりません。1000回の編集で、1000回のバグが発生する可能性があります。これは、DRYの原則がなぜあるのかを示す、ほとんど教科書的な定義です。

一方、通常のCSSを使用している場合は、'.button'というクラスを作成していると思います。そのクラスの中に入って、一行を変更すればいいのです。"background-color: 'red';" です。これで、そのクラス定義を使っている要素はすべて赤になります。

これで次のポイントが見えてきました。

HTMLはページの構造にのみ関心を持つべきで、ページのスタイリングには関心を持つべきではありません。

開発現場では「関心の分離」についてよく語られます。CSSモジュール(そして特に.vueファイル)は、サイトの同じ基本構成要素の構造、動作、スタイルを別々のフォルダに分ける必要があるという考えを払拭するために多くのことをしてきましたが、関心事項を分けることには何か意味があります。つまり、コードの各部分は、"疎結合かつ高度に凝集したもの "でなければなりません。

言い換えれば、HTML(構造構文)は、スタイルがどうあるべきかという情報を持つべきではなく、ページの構造に関する情報のみを持つべきなのです。

実際、CSSが発明された究極の理由、CSSの事業全体のポイントは、特にコンテンツとプレゼンテーションを分離できるようにすることでした。

それを実現する方法が「class」属性です。

classの目的は、ある要素が何であるかをコンピュータに伝えること、つまり、要素のコンテンツを記述することです。コンテンツを定義した後は、そのタイプのコンテンツがどのように見えるかを決めればよいのです。

これは、ページの基本的な構造を気にすることなく、要素の外観を変更できることを意味するだけでなく、要素が何であるかを記述するためにこれらのクラスを使用できることを意味しています。実際、BEMの名前付け構文の理由の1つは、BEMの名前は、コンポーネントが何であるかを示すだけでなく、ドキュメント内の他のコンポーネントとの関係も示すことができるからです。

私たちがコードを書くとき、2つの対象者のために書いていることを覚えておいてください。1つは、コードが実行される限り、コードの見た目は気にしないコンピュータ自身であり、もう1つは、あなたの同僚プログラマです。プログラムのどの部分がどうなっているのか、それらがどのように関係しているのかを彼らがすぐに理解できれば、バグを修正したり、機能を追加したり、組織に価値をもたらすことができるようになります。

可読性が悪い

Tailwindの入ったHTMLを見ると、"忙しい "とか "醜い "と感じるかもしれません。確かにその通りなのですが、それでは要点を逃しています。

インラインスタイルは、何が起こっているのかを知るための十分なコンテキストを提供しています。Tailwindのコードは、意味不明な略語であふれています。そのほとんどは、すでによく知られているCSSプロパティを再定義しただけのものです。

さらに悪いことに、それらが再定義ではない場合、それらは非常に不可解なものになります。Tailwindでは、メディアクエリの代わりにプレフィックス付きのクラス名を使用しています。Aleksandr Hovhannisyan氏の例をご紹介します。

<div
  class="w-16 h-16 rounded text-white bg-black py-1 px-2 m-1 text-sm md:w-32 md:h-32 md:rounded-md md:text-base lg:w-48 lg:h-48 lg:rounded-lg lg:text-lg"
>
  Yikes.
</div>

これは、下記のようにも表現できます

<style>
.thing {
  width: 16px;
  height: 16px;
  color: white;
  background-color: black;
  padding: 0.25rem 0.5rem;
  margin: 0.25rem;
  border-radius: 0.25rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
}

@media screen and (min-width: 768px) {
  .thing {
    width: 32px;
    height: 32px;
    border-radius: 0.375rem;
    font-size: 1rem;
    line-height: 1.5rem;
  }
}

@media screen and (min-width: 1024px) {
  .thing {
    width: 48px;
    height: 48px;
    border-radius: 0.5rem;
    font-size: 1.125rem;
    line-height: 1.75rem;
  }
}

</style>
<div class="thing">Yikes.</div>

はい、最初の例では確かにヒドく少ない量のコードの記述で済んでいることを私は認めます。しかし、2つ目の例がいかに明示的に特定のブレイクポイントでの高さと幅を定義しているかを見てください。

それは冗長です--生CSSがしばしばそうである様に。しかしそれにはSass/SCSSや、Emotion、Styled Componentsなどの別の解決方法があり、それらを使えばより簡潔な構文でも、その背後にある意味を失わずに済むのです。

繰り返しになりますが、これはプログラマーの常識です。先輩開発者が後輩開発者に、変数名を「const height = 10」ではなく「const h = 10」と命名することを非難するのもそのためです。

もうひとつの理由は、Tailwindのクラスは横に並べられていますが、CSSは縦に書かれています。文章の幅が広ければ広いほど、読者の目は次の行に進みにくくなりますし、横長の文章の中から探している特定の単語を見つけるのも難しくなります。

Tailwindのコードサンプルにある水平スクロールバーを見た瞬間、目が点になったのではないでしょうか?

標準CSSの多くの機能が使えない

この点についてはあまり触れませんが、TailwindではCSSの基本的な機能の多くを使うことができないことは指摘しておくべきでしょう。例えば、セレクタを連結することはできません。

.foo:focus,
.foo:active,
.foo:hover {
  /* css code */
}

結合子を使えません

.foo p {
  /* all p that are decendants of a .foo */
}
.foo > p {
  /* all p that are direct children of a .foo */
}
.foo + p {
  /* all p that are directly -after- a .foo */
}
.foo ~ p {
  /* all p that are siblings of a .foo */
}

Tailwindは存在しない問題を解決します

奇妙なことに、Tailwindのユーティリティクラスのパラダイムには明らかな制限があります。関連するスタイルをグループ化したい場合はどうすればいいでしょうか? "display:flex;"が "justify-content: {value}" なしに使われることはほとんどありません。CSSでは、これらのスタイルを(ちょっと待って)クラスにまとめることができます。

Tailwindでも、関連するクラスをまとめておくツールがあります。それは@applyと呼ばれるものです。これは、CSSファイルに記述する特別な非標準構文(ディレクティブ)で、Tailwindのクラスをまとめて1つのクラス名の下に配置することができます。

つまり、ユーティリティークラスのパラダイムの背後にある目的を完全に打ち破るものです。結局@applyを使わなければならないのであれば、*読みやすく、理解しやすく、修正しやすく、特別なツールや解析を必要としない、普通の一般的なCSSを使えばいいのではないでしょうか。CSSの構文は複雑ですが、90年代後半からかなり安定していて、すぐに激変することはありません。

とても簡単な想像の実験をしてみましょう。

CSSは開発されず、Tailwindのようなものが開発された世界を想像してみてください。つまり、ウェブページのスタイルは、個々のクラス名を繰り返すことでしか実現できない......おそらく、レイアウトにはテーブルタグを使うことになるでしょう。私が何歳かというと、1996年の高校3年生の夏休みにWebページのコーディングをしていたのですが、そのときにテーブルタグをたくさん使っていました。

もし、Tailwindの制限からCSSに移行できたとしたら、それは飛躍的な進歩だと思いませんか?表現力のある構文 意味のあるネーミング スタイルのグループ化 セレクタとコンビネータ!。アセンブリからC言語に初めて移行したようなものです。そうだとしたら、なぜ私たちはCSSを、できることが少なく、より複雑で、質の悪いコードベースを生み出し、将来的には大規模なベンダーロックになってしまうようなものに置き換えようと考えているのでしょうか?

CSSより良いものが欲しいなら、解決策は既にあります

Tailwindの宣伝文句の多くは、CSSを取り除くことができるというものでした。CSSの扱いが難しいことは誰もが知っています。特に、CSSがうまく書かれていないレガシーなコードベースを持っている場合には。

しかし、ほとんどの場合、CSSにはスタイリングをよりシンプルにするための改良が施されています。例えば、Javascriptの力を利用して動的なクラス定義を可能にする様々なCSS-in-JSソリューション、Sass/SCSS/LESSなどのプリプロセッサ、Stylelintなどのリンター、BEM/SMACSSなどのベストプラクティスメソッドなどがあります。これらの技術を学ぶことにオーバーヘッドはありますか?はい。ビルドチェーンの一部として必要なツールはありますか?そうです。しかし、Tailwindとは異なり、これらのソリューションはすべて、あなたのコードに具体的な利益を提供します - これはTailwindが主張できないことです。

文字通り何の価値もなく、大量の問題を抱えています

結局、これらの問題を解決して何が得られるのでしょうか?何が残るのでしょうか?基本的には、インラインスタイルの読みにくさと複雑さを改善したものです。

Tailwindを採用すると、今後何年にもわたってあなたとあなたのチームに問題をもたらすことになり、それを取り除くのは難しいでしょう。


コメント欄からの回答をもとに更新。

コメント欄からの回答をもとに、いくつかの注意点をご紹介します。

気に入らないものをなぜゴミよばわりするのか?

良いフレームワークについて書くのと同様に、悪いフレームワークについても書くことは重要ですが、それには2つの理由があります。

まず、ジョン・スチュワート・ミルの「間違った考えの価値」という議論があります。これは、間違っていることを(善意で)主張することで、分析と反論によって、より正しく、より完全な見解に到達するというものです。アイディアは常に挑戦し続けなければ、陳腐化してしまいます。確かに、「相手の主張を理解できない者は、自分の主張も理解できない」というのは、私が心がけている言葉です。この記事を書いたとき、私はTailwindの良いところを探そうとしました。なぜ人々はそれが好きなのか?(CSSを書かなくてもいい。HTMLの中にスタイル情報を入れることができます。簡潔なコードが書ける。CSSではできないことができるようになる。) 人々がなぜそれを好んでいるのかがわかれば、自分がなぜ好まないのかをよりよく理解できるようになりました。(コンテンツとプレゼンテーションの密結合・メンテナンスが難しくなる・構文が不明瞭になる・cssでできることができなくなってしまう)

2つ目は、将来的に誰かがチームでメンテナンスしなければならないアプリにTailwindを加えるべきか考えるでしょう。そして、「TailwindCSSの長所と短所」をグーグルで検索するでしょう。長所を説明する記事がたくさん出てきます。ここに短所を説明した記事があります。願わくば、私がTailwindを使わないように説得力のある議論をして、将来の開発者がTailwindに対処しなくて済むようにしたいものです。

Tailwindを好きな人たちに失礼だよ

『こんなのニューオリンズジャズじゃないよ!』

私はニューオリンズ・ジャズは好きじゃないですが、聴かなくてもいいですし、ニューオリンズジャズのアルバムは買いません。
ニューオリンズ・ジャズの作曲上の問題点と思われる点について、細かく批判する習慣もありません。

しかし、チームリーダーやプロダクトオーナー、ステークホルダーが私のところに来てこう言ったことはありません。"次のプロジェクトでは、チームの全員がニューオリンズ・ジャズを理解し、演奏できるようにならなければならないと思っています。"

エンジニアや開発者は、自分が好きではないだけでなく、自分の仕事を困難にするような技術を使わなければならないことがよくあります。それは、意思決定者がソフトウェアのトレードオフを気にしなかったか、知らなかったかのどちらかの理由によるものです。前者についてはどうすることもできませんが、後者についてはどうかすることができます。

チームリーダーが新しい技術を自分たちの技術スタックに取り入れようと考えたとき、それを試す価値があるかどうかを評価するために、このようなブログ記事を参考にすべきでしょう。

私の記事は、あなたが考えているような、「私がTailwindを好きではないから、あなたもTailwindを好きではないはずだ」というものではありません。それは12歳の子供の技術批判の視点です。

そうではなく、私の主張は "ミッションクリティカルなアプリケーションにTailwindを選択した場合、あなたの仕事は難しくなり、アプリケーションはより脆くなり、長期的にはあなたのチームは苦しむことになるでしょう"ということです。

しかし、CSSには大きな問題があります。

本当にそうですね。そして、プレーンなCSSよりも良い解決策があります。しかし、Tailwindはその一つではありません。

1990年代、家を建てるには平らな石で釘を打つしか方法がなかったとします(CSS)。ところが2000年代半ばになって、頭のいい人が「ハンマー」を発明しました。(SCSS)調整が必要で、新しい道具を覚えなければなりませんが、仕事はずっとうまくいきました。

2010年代の初めから半ばにかけて、別の人が「釘打ち機」(CSS-in-JS)を発明しました。ハンマーと同じようなことができますが、使い方を知らなければなりません。トレードオフもありましたが、一般的には、ハンマーや釘打ち機を使って仕事をすることを選んだ人は、たいてい大丈夫でした。多くの人は、手動のハンマーが適切と思われるときには手動のハンマーを使い、必要と思われるときには釘打ち機を使うことが多かった。そして、大工の世界ではすべてが順調でした。

そして2017年、ある人が大工さんたちのところにやってきて言いました。"おい、俺がこうしたらどうなるか見てみろ!"と言って、装填したリボルバーの尻の部分で釘を打ち始めたのです(Tailwind)。

そしてそれを支持する人たちは、石で叩くよりも家を建てるのに有効であることをすぐに指摘します。

"でも、それは弾の入った銃だ。誰かを撃ってしまうかもしれない。"
"まだ起きたことはないよ"
"なぜハンマーを使わないんだ?釘打ち機でもいいよ。"
"ハンマーも釘打ち機も嫌いだ"
"使いたくない気持ちはわかるが、仮に石を使ったとしても、長い目で見ればその方が安全だ。"
"でも、石を使うのはとても難しいし、効率も悪い。"
"石を使えと言っているのではありません。私が言いたいのは、ハンマーがすでに石の持つ問題を解決しているということです。しかし、石であっても、誰も撃たないので、装填された銃よりも優れた道具なのです。"
"でも、私は銃を愛しています"
"自分の敷地内での小さなプロジェクトに銃を使うのは構わないと思うが..."
"いや、俺は現場監督だ。これからは現場のみんなが装填した銃を使うんだ、だってすごいんだから"

更新日:2021年5月9日 - この記事に反論しようとしているMykolas Mankevicius氏のブログ記事をご覧ください。もちろん私はそうは思いませんが、この記事は議論を深めるものだと思います。もしあなたがこの記事を読んでtailwindを使うかどうかを決めているのであれば、この問題の「反対側」の意見を聞くべきでしょう。
同意はしているが、私の書き方が強引すぎるのでは?Tailwind CSS may not for youと題されたこの記事に対するBenoît Rouleau氏の見解をご覧ください。
Cherは、"Sexism, Racism, Toxic Positivity, and TailwindCSS "の中で、この記事が得たいくつかの反響と、それが私たち自身の無意識のバイアスとどのように関連しているかについて書いています。

120
51
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
120
51