1 ポイント 投稿者 GN⁺ 1 시간 전 | 1件のコメント | WhatsAppで共有
  • いくつかのサイトを Tailwind からセマンティックHTMLとバニラCSSへ移行し、Tailwindが提供していたルールのうち必要なものだけを自分で再実装した
  • Tailwindの preflight reset、カラーパレット、font scale のような慣れ親しんだ仕組みは維持しつつ、CSS変数とファイル分割によってバニラCSSへ移し替えた
  • CSSの大半は コンポーネントごとのファイル に分け、固有クラスを持たせることで、あるコンポーネントの修正が別のコンポーネントをひそかに壊す可能性を減らした
  • Tailwindを離れる背景には、最近のTailwindの ビルドシステム依存、2.8MBの tailwind.min.css、バニラCSSとの混在、CSS上の制約がある
  • レスポンシブ設計では breakpoint よりも CSS gridauto-fitgrid-template-areas をより活用しようとしており、@layer@scope、container queries も学習対象としている

Tailwindで学んだ構造をバニラCSSへ移す

  • 8年前にTailwindを初めて使ったときは、CSSコードをどう構造化すべきか分かっておらず、完全な混乱よりはTailwindのほうがずっと良い選択だった
  • 最近およそ1週間、いくつかのサイトをTailwindから セマンティックHTML + バニラCSS へ移行しながら、Tailwindが提供していたルールのうち必要な部分だけを自分で選んで再実装することになった
  • A whole cascade of layersHow I write CSS in 2024 を読み、どんなCSSコードベースにも、レイアウト・フォント・色・共通コンポーネントといった異なる関心事を管理するための仕組みが必要だということが明確になった
  • Tailwindには reset stylesheetカラーパレットfont scale のような仕組みがすでにあり、慣れていて便利な部分はバニラCSSでも模倣できる

CSSコードベースに置いた主な仕組み

  • reset

    • Tailwindの preflight stylestailwind.css から最初の約200行コピーして使っている
    • Tailwindのresetには長く慣れていて、すべての要素に box-sizing: border-box を適用するルールは、要素の幅に padding を含めるようにしてくれる
      * { box-sizing: border-box; }
    
    • html {line-height: 1.5;} のようなほかのresetルールにも無意識に依存している可能性があり、こうしたルールなしでCSSを書くには大きな適応が必要そうだ
  • components

    • CSSの大半は、VueやReactのコンポーネントに近い形で コンポーネントごとのファイル に整理している
    • 各コンポーネントは固有クラスを持ち、あるコンポーネントのCSSが別のコンポーネントのCSSを上書きしないようにしている
    • 実際に変更したいCSSの約80%はコンポーネントファイル内にあるので、100行のコンポーネントを編集するときはその100行だけを考えればよい
    • たとえば .zine コンポーネントは次のようなHTMLを持てる
      <figure class="zine horizontal">
          <img src="whatever.jpg">
      </figure>
    
    • CSSではネストされたセレクタで .horizontal.vertical:hover のような状態をコンポーネント内部にまとめている
      .zine {
        ...
        &.horizontal {
          ...
        }
        &.vertical {
          ...
        }
        &:hover {
          ...
        }
      }
    
    • Web Components や @scope のように、コンポーネント間の干渉をプログラム的に防いではいないが、慣習を定めて守るだけでもかなり改善した感覚がある
  • colours

    • colours.css には、必要なときに使えるCSS変数をまとめている
    • 色は難しく、今回のリファクタリングで色の使い方を見直したくはなかったため、既存のやり方を維持している
    • 唯一のルールは、サイトで使うすべての色をこのファイルに列挙することだ
      :root {
        --pink: #fea0c2;
        --pink-light: #F9B9B9;
        --red: #f91a55;
        --orange: rgb(222, 117, 31);
        ...
      }
    
  • font sizes

    • Tailwindでは text-lgxl2xl のようにサイズ段階を選ぶだけでよかったので、empxrem のどれを使うか覚えておく必要がなかった
    • これをバニラCSSでも維持するため、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-weight: var(--line-weight-lg);
      }
    
  • utilities

    • 複数のコンポーネントで繰り返し使うボタンのような要素は utilities に分類している
    • スクリーンリーダー利用者にだけ見せるべき要素のための .sr-only のような一部のユーティリティクラスはTailwindからコピーした
    • この領域は小さく保ち、変更時には慎重に扱いたい
  • base

    • “base” スタイルはサイト全体に直接適用するスタイルだ
    • サイト全体に多くのスタイルを強制するほどの確信はないため、この領域はごく小さく保っている
    • 現時点でよいと感じているルールは <section>a の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);
      }
    
    • baseスタイルは最初はほぼ空のままにしておき、共通してほしいものが見つかったときにコンポーネントからbaseへ移す ボトムアップ方式 が最も簡単そうだ
  • spacing

    • padding と margin をどう管理するかは、まだ完全には決まっていない
    • Tailwindを使っていたときは、望む見た目になるまで padding と margin をあちこちに即興で入れていて、今はそれより原則的なやり方を探している
    • 現在は、できるだけ外側のレイアウトコンポーネントが余白を担当するようにしたいと考えている
    • 複数の子を持つ <section> で、子要素同士の間隔を均等に空けたいときは次のルールが使える
      section > *+* {
        margin-top: 1rem;
      }
    
  • responsive design

    • Tailwindでは md:text-xl のように、特定サイズ以上で text-xl スタイルを適用する メディアクエリベースの構文 を多用していた
    • 今は breakpoint をあまり使わなくても済む、より柔軟な CSS grid レイアウトを作ろうとしている
    • auto-fit を使えば、大きな画面では2カラム、小さな画面では1カラムを自動で使える
      display: grid;
        grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), max-content));
        justify-content: center;
    
  • build system

    • 開発中は別途ビルドシステムは必要ない
    • CSSには組み込みの @import 文があり、ファイルを分けて読み込める
      @import "reset.css";
      @import "typography.css";
      @import "colors.css";
    
    • CSSにはネストされたセレクタも組み込まれている
      .page {
        h2 { ...}
      }
    
    • 本番用にCSSファイルをまとめたければ esbuild を使える
      esbuild style.css --bundle --loader:.svg=dataurl  --loader:.woff2=file --outfile=/tmp/out.css
    
    • ふだんはCSSやJSのビルドシステムを使うのを避けているが、esbuild はWeb標準ベースで静的なGoバイナリなので問題ないと考えている
    • esbuild については2021年に esbuildとVueに関する記事 を書いたことがある

Tailwindを離れる理由

  • Tailwindは2018年以降、ビルドシステム依存 がはるかに強くなっており、最近のTailwindをビルドシステムなしで使うのは不可能に見えるため、ここ数年はTailwind v2を使ってきた
  • ビルドシステムなしでTailwindを使う代替として litewind があるようだ
  • Tailwindはもともとビルドシステムと一緒に使う前提だったが、実際にはそうしていなかったため、多くのプロジェクトに 2.8MB の tailwind.min.css ファイルが残っており、ややちぐはぐに感じられた
  • Tailwindを初めて使った頃より、CSSの腕前が上がった
  • Tailwindには最終的には制約があり、CSSで奇妙だったり特殊だったりすることをしたいとき、いつでも可能とは限らない
  • そうした制約はとても有用なこともあり、実際バニラCSSへ移行する中でTailwindの制約の一部を再実装しているが、今は必要な制約だけを選んで使いたいと思うようになった
  • 同じプロジェクトの中でバニラCSSとTailwindが混在するサイトが生まれ、それをメンテナンスするのは楽しくなかった
  • もっと セマンティックなHTML を書くとどんな感覚なのか気になっていた

これから学んでみたいCSS機能

  • @layer は cascade layer を扱う機能で、まだ使っていないが学んでみたい機能だ
  • @scope はコンポーネントや特定範囲内のスタイルを扱ううえで興味を引かれる機能だ
  • container queries はコンテナ基準のレスポンシブ設計のための機能で、学んでみたい
  • subgrid は CSS grid 関連の機能として関心リストに入っている

Tailwindを全面否定しない結論

  • 今はTailwindを離れつつあるが、Tailwindを使い始めたこと自体には今でも満足している
  • Tailwindを使いながら多くのことを学び、tailwind.min.css を削除したあとでもサイト内でTailwindの一部を引き続き使える
  • wizardzines.com のCSSをもともと設計して書いた Melody Starling のおかげで、サイトのクールで楽しい部分が生まれた
  • CSS作業の中で CSS TricksSmashing Magazine などの多くのCSS記事を読み、CSSコミュニティが実践方法を数多く共有してくれてとても助けられた

1件のコメント

 
GN⁺ 1 시간 전
Lobste.rsのコメント
  • 個人プロジェクトでは、もう CSS/JavaScriptフレームワーク をほとんど使っていない
    依存関係がなければ、サプライチェーン脆弱性も発生しようがないから。もちろん脆弱性はそれだけではないが、助けにはなる

    • 私もかなり 素のHTML/CSS/JS に戻っていて、自作のものを少し載せて使う程度になっている
      フレームワーク疲れ、npm audit の負荷、そしてLLMのおかげで実装方法について他人の評価をあまり気にしなくてよくなったことが合わさった結果だ。たとえば「なぜReactやTailwindを使わないのか」といった質問など
  • これは単に CSSが動く仕組み というだけの話だ
    これを知らずにTailwindを盲目的に使っているのを見ると、外に出て雲に向かって叫びたくなる。私にはTailwindの90%は文法が違うだけのインラインスタイルに見え、<FONT> タグより一段ましな程度だとも思える

    • このコメントの意図はよく分からないが、8年近くTailwind を使ってきて、Tailwind利用者を見下すこういうコメントは数え切れないほど見てきたし、そのどれ一つとしてTailwindをやめる助けにもCSSの腕を上げる助けにもならなかった
      このブログ記事は、私が実際に知る必要があった内容を説明している
    • 「Tailwindの90%は文法が違うだけのインラインスタイル」というのは、あまり正確ではない
      Tailwindはインラインスタイルとはかなり異なる動きをし、むしろCSSにはるかに近い。記事でも指摘されているように、Tailwindをうまく使うための良い習慣の多くは、効果的なCSSを書くためにも必要な習慣だ。Tailwindは、すべての要素に暗黙の スコープ付きCSSブロック を付与しつつ、独自のDSLを使うものに近い
    • CSSがどう動くかを知っていることと、効果的に使う方法 を知っていることの間には大きな差がある
      CSSの動作原理はよく分かっているが、素のCSSは負担が大きく、グラフィックデザインも得意ではないので、今でもTailwindを使っている。この記事は、Tailwindを足がかりにCSSを構造化するためのアイデアを与えてくれる
  • 最近の流れをあまり追えていない立場からすると、この記事は モダンなCSSの実践 をかなりうまく示しているように思う
    インスピレーション元の記事へつながるリンクが多いのも気に入った。読み物として良さそうで、今のところは "no outer margin" だけ読んでみた
    ただ、基本スタイルを「下から上へ」組み立てるアプローチには少し懐疑的だ。代わりに何をすべきかは分からないし、試してみる価値はありそうだが、基本スタイルは本質的に扱いが難しい

  • この記事は本当に良かった
    私も小さなサイトをあれこれ作りながら少しずつCSSを学んできたので、最初からこういう システム的な考え方 をもっとしていれば助けになっただろうと思う。フレームワークにはかなり抵抗感があるが、使わないでいると、やりたいものを実装できても構造のない宙空に浮いているような感覚になることがよくあった

  • 「Tailwindはよくないから単にCSSを使え」ではなく、「Tailwindは素晴らしいが、もう必要ないかもしれない」という言い方なのが良い
    CSSを手で構造化することにいつも苦労していたが、この記事のおかげでずいぶん違う観点で考えられるようになった

  • CSSを整理するとき、この 構造化手法 はかなり役に立った: https://rstacruz.github.io/rscss/
    全体として、元記事でjvnsが説明していた内容とよく合っていて、その上に構造と整理を少し追加してくれる