Moving away from Tailwind, and learning to structure my CSS

Julia Evans

Tailwindから離れて、CSSの設計を学ぶ

原文は Julia Evans により に公開されました。 このブログを購読する

こんにちは!8年前に、私はTailwindとの出会いについて興奮気味に書きました

当時の私はCSSコードをどう設計すればいいのかまったくわかっておらず、完全なカオスの山とTailwindのどちらかを選べと言われたら、喜んでTailwindを選びました。おかげでたくさんの小さなサイトを作ることができました!

この1週間ほど、いくつかのサイトをTailwindから、よりセマンティックなHTML+素のCSSへと移行する作業をしていました。めちゃくちゃ楽しくて、めちゃくちゃ興味深かったので、学んだことをいくつかシェアします!

いつものことですが、私はフルタイムのフロントエンド開発者ではないので、CSSの学習は長年にわたって断続的に進んできました。

結局、Tailwindからたくさん学んでいたことがわかった

CSSの設計について考え始めたときは、最初はちょっと気後れしました。自分はCSSの設計があまり得意ではないので!でも、CSSの設計方法について語るブログ記事(A whole cascade of layersHow I write CSS in 2024など)を読み始めて、いくつか気づいたことがありました。

  1. あらゆるCSSのコードベースでは、さまざまなことが同時に起きています(レイアウト!フォント!色!共通コンポーネント!)
  2. それぞれを管理するための仕組みやガイドラインがあると非常に役立ちます。そうでないとすぐにカオスに陥ってしまいます
  3. Tailwindはそのうちのいくつかについて仕組みを持っていて、私はすでにそれらの仕組みを知っている!気に入った仕組みを真似すればいいんだ!

たとえば、Tailwindには次のようなものがあります。

これから話す仕組み

これから、CSSコードベースのいくつかの側面と、それぞれについてコードベースにどんなルールを課したいと考えているかを話します。Tailwindから真似したものもあれば、そうでないものもあります。

  1. リセット
  2. コンポーネント
  3. フォントサイズ
  4. ユーティリティクラス
  5. ベース
  6. 余白
  7. レスポンシブデザイン
  8. ビルドシステム

1. リセット

Tailwindの「preflight styles」を、tailwind.cssを開いて最初の200行ほどをコピーしてそのまま使いました。

やっていて気づいたのですが、いつの間にかTailwindのCSSリセットにすっかり慣れ親しんでいました。たとえばTailwindはすべての要素にbox-sizing: border-boxを設定しています(要素の幅にpaddingが含まれる、という意味です)。

* { box-sizing: border-box; }

これらなしでCSSを書くとなると、私にとってはかなり大きな変化になると思います。Tailwindのリセットには、きっと他にも(html {line-height: 1.5;}のような)無意識に慣れ親しんでいて、存在すら気づいていないものがたくさんあるはずです。

2. コンポーネント

ここからがCSSの大部分です!

ここでの考え方は、CSSを「コンポーネント」ごとに整理するというものです。精神的にはVueやReactのコンポーネントに近い発想です(といっても、サイトにJavaScriptがまったくなくてもかまいません)。

基本的な考え方はこうです。

  1. 各「コンポーネント」は固有のクラスを持つ
  2. あるコンポーネントのCSSが、他のコンポーネントのCSSを上書きすることはない
  3. 各コンポーネントは独自のCSSファイルを持つ

つまり、あるコンポーネントのCSSを編集しても、別のコンポーネントの何かが謎に壊れることはありません。そして、実際に変更したいCSSの80%くらいは各コンポーネントのファイルに入っているので、100行のコンポーネントを編集するなら、その100行だけを考えればいい。私にとっては考えるのがずっと楽になります。

たとえば、このHTMLは.zineという「コンポーネント」だとします。

<figure class="zine horizontal">
    <img src="whatever.jpg">
</figure>

そしてCSSは、ネストしたセレクタを使ってこんな感じになります。

.zine {
  ...
  &.horizontal {
    ...
  }
  &.vertical {
    ...
  }
  &:hover {
    ...
  }
}

コンポーネント同士が干渉しないことを保証するようなプログラム的な仕組み(ウェブコンポーネントや@scopeなど)はまだ導入していませんが、ただ規約を設けてベストを尽くすだけでも、すでに大きな改善に感じられます。

次は、サイト全体で一貫性を保ち、これらのコンポーネント同士の足並みをそろえるための規約です!

3. 色

colours.cssには、必要に応じて使える変数がこんな感じでたくさん入っています。色は本当に難しいので、今回のリファクタでは色の使い方を見直したくなくて、そのままにしました。

ここで守ろうとしているルールはただ一つ、サイトで使うすべての色はこのファイルに列挙する、ということです。

:root {
  --pink: #fea0c2;
  --pink-light: #F9B9B9;
  --red: #f91a55;
  --orange: rgb(222, 117, 31);
  ...
}

4. フォントサイズ

Tailwindで気に入っていたことの一つは、フォントサイズを設定したいときに「うーん、文字を大きくしたいな」と思ったらtext-lgと書くだけで終わることでした!もしそれでも足りなければxl2xlにすればいい。emなのかpxなのかremなのかを思い出そうとする必要もありません。

そこでTailwindから拝借して、こんな感じで変数をたくさん定義しました。

  --size-xs: 0.75rem;
  --line-height-xs: 1rem;

  --size-sm: 0.875rem;
  --line-height-sm: 1.25rem;

あとはフォントサイズを設定したいときは、こんなふうにします。Tailwindよりは少し冗長ですが、今のところはこれで満足しています。

h3 {
  font-size: var(--size-lg);
  line-height: var(--line-height-lg);
}

5. ユーティリティ

ボタンのように、多くの異なるコンポーネントに登場するものがあります。これらを私は「ユーティリティ」と呼んでいます。

Tailwindからいくつかのユーティリティクラスをコピーしました(スクリーンリーダーのユーザーにだけ表示したいもののための.sr-onlyなど)。

このセクションはかなり小さく、ここでの変更は慎重に行うようにしています。

6. ベース

「ベース」スタイルは、サイト全体に適用されるスタイルのうち、自分で選んだものです。サイト全体にたくさんのスタイルを強制する自信がないので、このセクションはとても小さく保つ必要があります。今のところ安心して置けているのはこの2つだけで、<section>の方は変えるかもしれません。

/* put a 950px column in the middle of each <section> */
section {
  --inner-width: 950px;
  padding: 3rem max(1rem, (100% - var(--inner-width))/2);
}

a {
  color: var(--orange);
}

ベーススタイルについては、ボトムアップで進めるのが私には一番やりやすそうです。最初はベーススタイルにはほとんど何も入れず、共通して使いたいものが見つかるたびに、コンポーネントからベーススタイルへ移していく、というやり方です。

7. 余白

paddingやmarginの管理方法については、まだ完全には方針が固まっていません。ただ、Tailwindでやっていたときよりはもう少し筋の通ったやり方をしようとしています。Tailwindでは、思いつくままにあちこちへpaddingやmarginを置いて、見た目が整うまでやみくもに調整していました。

今は、できるだけ外側のレイアウトコンポーネントに余白の管理を任せる方向で進めています。たとえば、たくさんの子要素を持つ<section>があって、それらの間に余白を入れたい場合、子要素を均等に配置するためにこんなふうに書くかもしれません。

section > *+* {
  margin-top: 1rem;
}

参考にしたブログ記事:

8. レスポンシブデザイン:もっとgridを使おう!

Tailwindで私がやっていたレスポンシブデザインは、メディアクエリをたくさん使う方法でした。Tailwindにはmd:text-xlという記法があって、これは「md以上のサイズでtext-xlのスタイルを適用する」という意味です。

今はかなり違うアプローチを試しています。ブレークポイントをそれほど必要としない、より柔軟なCSS gridレイアウトを作るというものです。これは難しいですが、gridで何ができるのかを学ぶのは本当に面白く、Tailwindではできないことの良い例だと思います。

たとえば、auto-fitを使って、大きな画面では自動的に2カラム、小さな画面では1カラムにする方法をこんなふうに学んでいるところです。

  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), max-content));
  justify-content: center;

また、grid-template-areasもたくさん使いました。これは素晴らしい機能で、Tailwindでは使えないはずです。

参考:

9. ビルドシステム:esbuild

開発中は、ビルドシステムは必要ありません。CSSには今や組み込みのimport文があります。こんな感じです。

@import "reset.css";
@import "typography.css";
@import "colors.css";

そして組み込みのネストセレクタもあります。こんな感じです。

.page {
  h2 { ...}
}

必要なら、本番用にCSSファイルをバンドルするのにesbuildを使えます。こんな感じになります。

esbuild style.css --bundle --loader:.svg=dataurl  --loader:.woff2=file --outfile=/tmp/out.css

普段はCSSやJSのビルドシステムは避けているのですが、esbuild2021年にここで書きました)はウェブ標準に基づいているし、静的なGoバイナリなので、使うのに抵抗がありません。

なぜTailwindから移行したのか?

なぜTailwindから移行したのか、と何人かに聞かれました。理由はいくつかあります。

  • Tailwindは2018年以降、ビルドシステムへの依存がずっと強くなりました。新しいバージョンのTailwindをビルドシステムなしで使うのは不可能(?)だと思います。なので私は長年Tailwind v2を使い続けてきました(litewindというものもあるらしいですが)。
  • もともとTailwindはビルドシステムと一緒に使うのが前提なのですが、私はそれをずっとやってこなかったので、多くのプロジェクトで2.8MB(gzipで270K)のtailwind.min.cssを抱えることになり、ちょっとばかばかしく感じていました。
  • Tailwindを使い始めた頃と比べて、私はCSSがずっと得意になりました
  • 結局のところTailwindには限界があります。CSSでちょっと変わったことをやろうとしても、Tailwindでは必ずしも実現できません。そうした制約は非常に役に立つこともあります(この記事の多くは、Tailwindの制約を自分で再実装する話です!)が、今の私としては、何を制約として残すかを自分で選びたいと思っています。
  • 同じプロジェクト内で素のCSSとTailwindが混在するサイトになってしまい、その保守が楽しくありませんでした
  • よりセマンティックなHTMLを書くのがどんな感じなのか、興味が湧きました。

気になっているCSS機能

今回の作業で、使ってはいないけれどいつか学んでみたいCSS機能をたくさん知りました。

Tailwindから離れたもう一つの理由

この記事ではTailwindを使うことで学んだことをたくさん話してきましたが、それはどれも本当のことです。

でも、3年前にTailwind and the Femininity of CSSという記事を読んで、それがずっと心に残っています。正直なところ、私も最初はその記事が描写しているようなCSSへの態度を持っていたと思います。

彼らはそれがシンプルだと聞いたので、簡単なのだろうと思い込む。だが実際に使ってみると、うまくいかない。これは言語のせいに違いない、だって自分は賢いし、これは簡単なはずなのだから。

でもこの10年で、私はCSSという技術を本当に愛し、尊敬するようになりました。

だから何年も前に、「CSSは難しい」という感覚に対して、CSSを軽視するのではなく、CSSをもっと上達して一つの技術として真剣に向き合おうと決めました。そうしたことで、すべてが変わりました。私の不満の多く(「中央寄せは不可能」など)は、とっくの昔にCSSで解決されていたことを知りましたし、「中央寄せ」が何を意味するのかは必ずしも自明ではなく、やり方が複数あるのが当然だということもわかりました。CSSが難しいのは、難しい問題を解こうとしているからなのです!

この10〜15年で作られてきた新しいCSS機能(この記事で触れたものもいくつかあります!)と、それらがCSSを使いやすくしてくれていることに、私はとても感心しています。そしてCSSスキルを磨くために時間を費やすことは、本当に素晴らしい経験でした。

そしてあの記事は、TailwindがCSSの専門知識の価値を下げることに加担していると感じさせました。Tailwindが私個人にとって有用なツールであったとしても、そうしたことに加担したくはないと思ったのです。特にLLMの時代には、人間の専門知識を大切にすることが、これまで以上に重要に感じられます。

私に影響を与えた、Tailwindを批判する別のブログ記事:

以上です!

wizardzines.comのCSSを最初にデザインし、書いてくれたMelody Starlingに感謝します。サイトのクールで楽しいところはすべてMelodyのおかげです。

また、今回の作業中にCSSについての素晴らしいブログ記事をたくさん読みました(CSS TricksSmashing Magazineなどから)。この記事の中でもいくつかリンクを貼ってみましたが、CSSコミュニティの人たちが自分たちの実践を惜しみなく共有してくれていることに、本当に感謝しています。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント