スポンサーリンク

AIにCSSを書かせる最適解を探したら、CSS設計の問題じゃなかった

AI
Sleeping panda

AIにコーディングを任せる前提で、CSSの設計を見直そうとしました。「FLOCSSを卒業して、もっとAIが書きやすい構造にすべきでは?」と。

数日かけて考え、最後はAIにも討論させて、出た結論はこうです。

CSSの「流派」は最重要変数じゃない。効くのはスコープの局所性と、設計図の外側=プロセス層(規約・制約・レビュー)だった。

拍子抜けかもしれませんが、これが一番の収穫でした。順番に書きます。

先に断っておくと、今の主流は「AI時代=Tailwind最強」です。それは承知しています。
この記事はその空気に真正面から逆らう話ではなく、「フリーフォームな実測デザイン × そのCSSを読むのは自分とAIだけ」という特定条件では、定番の結論(Tailwind)が当てはまらなかった、という現場報告です。前提が違えば結論も変わるので、まず条件を置きます。

前提(ここが結論を決める)

私の現場はこういう条件です。

  • 受託のコーディングで、デザインは一貫スケールに乗っていないフリーフォーム(ピクセル実測で忠実に起こす)。
  • そのCSSを読むのは、実質「自分」と「AI」だけ。第三者がメンテする前提がない。
  • 一番の敵は認知負債——AIが書いた変更が、自分の把握速度を超えて積み上がり、自分のコードベースを信頼できなくなること。

この前提を外すと結論が変わるので、最初に置いておきます。

仮説はいくつも潰れた

最初は素直に候補を並べました。

  • Tokens + Component(2層):方向は良い。でも「2層に圧縮」は理想論で、実資産に当てるとレイヤー数は本質じゃなかった。
  • Tailwind / utility-first:AIの訓練データが圧倒的で「AIが書く」だけなら最強候補。実際「BEM疲れ → だからTailwind」は今や定番の結論です。ここまでは私も同意——BEM/FLOCSSの命名・分類判断がAIに辛いのは事実。でもそこから先が分かれます。フリーフォーム実測だと p-[37px] mt-[53px]任意値の山になり、utilityの旨味(統一スケールの再利用)が死ぬ。スケールに乗らないデザインは、Tailwindにとって最悪の相性。私の現場では不利でした。
  • 自作CSSフレームワーク:一番やりたくなる。でもAIは「訓練データに大量にある慣習」が一番得意で、独自記法は事前知識ゼロ=毎回教える必要・ドリフトが増える。「AI最適のつもりが逆にAI不利」という矛盾。

ここで気づきます。手段(自作・新パラダイム)が、目的(AI最適)を裏切っている

AIに討論させた

一人で結論を出すと盲点が怖いので、ClaudeCodeとCodexに同じ問いを、それぞれ別の立場(Tailwind推進・純モダンCSS・レビュー重視の審判)で討論させました。結果は4対1でTailwind不採用。賛成は「推進役」を割り当てた1人だけ。

そこで出た核心が2つあります。

核心1:utilityとcomponentの切り分けは「切り分けさせない」

ずっと「AIにどうやってutilityとcomponentを切り分けさせるか」で悩んでいました。でも汎用の切り分けルールは存在しないんです。「再利用性で分ける」も「簡単/複雑で分ける」も「layoutはutility・見た目はcomponent」も、フリーフォーム実測では全部破綻します(だってlayoutこそ見た目だから)。

解は逆転発想でした。

  • 既定はすべて component CSS(見た目・余白・配置・状態差分)。迷ったら必ずcomponent。
  • utility は「閉じた許可リスト」だけ。任意値・spacing・color・font-size を持たない、文脈非依存のものに限定する。
// utility は、この程度の"非デザインの汎用補助"だけ。
.u-hidden { display: none; }
.u-fullBleed { width: 100vw; margin-inline: calc(50% - 50vw); }

AIに「これはutilityか?」を判断させない。判断点がゼロなら、生成のブレも認知負債も生まれない。「Tailwindで全部やる」を突き詰めても、結局この許可リスト運用に行き着く——なら依存を背負う理由がない、という結論でした。

核心2:効くのは「流派」でなく、スコープ局所性とプロセス層

AIがCSSで事故るのは「翻訳」じゃなく「波及」です。変更した一箇所が、別ページ・別状態を壊す。これを減らすのはBEMかTailwindかという宗派ではなく、

  • @layer でカスケード順を固定
  • :root には「全体トークンだけ」。コンポーネント固有の実測値は局所変数か生pxで、そのcomponentに閉じる
  • ネスト&スコープで変更の波及範囲を物理的に小さく保つ
@layer reset, tokens, base, components, utilities;

そして本当の梃子は、CSSの外側にありました。

  • 規約を機械化(色はtoken経由、をlintで強制)
  • 小さいdiff+AIの「判断」を申告させる(コード全部を読まずに、何を決めたかだけ見る)
  • VRT(見た目の回帰テスト)=承認済みの見た目の「外部記憶」

AIが書いた変更を「diffで一目で監査できるか」。問うべきはそこだけで、パラダイム論争は半分くらい的外れだったわけです。

FLOCSSへのリスペクト

ここまで読むと「FLOCSS否定」に見えるかもしれませんが、逆です。むしろよく出来ていたと再認識しました。

捨てたのは2つだけ:

  1. per-styleの分類判断(このスタイルはComponentかProjectかUtilityか、を毎回AIに決めさせる)=AIが最も苦手な「未来予測」
  2. 手動のカスケード制御(命名規律で詳細度を管理)→ これは @layer がネイティブに解決

逆に、「サイト骨格(layout)・再利用部品(component)・ページ固有」というロール分けは残しました。フォルダで分けると探しやすい。これは結局、FLOCSSのLayout層の知恵の再発見です。l- を捨てても、その思想は正しかった。

着地点

最終的に落ち着いたのは、こうです。

  • モダンCSS(component-first)+ @layer:rootトークン + 許可リスト制の極小utility
  • フォルダは layout / ui / <page> のロール分け(全部 @layer components 出力)
  • 色だけlint強制、余白はフリーフォーム実測なので生pxまたはrem
  • 変種は data-variant、状態は data-state/.is-、固定サイズスケールはマップ生成のmodifier
  • 派手なアニメが要る時だけライブラリ(GSAP等)を該当ページに

Tailwindでもなく、自作FWでもなく、「標準に寄せて、薄い規約と検証で締める」。地味ですが、それが正解でした。

一番の学び

技術記事っぽい結論より、本当の学びはメタな所にあります。

「CSSの構造を作り変えれば解決する」と思い込んでいたこと自体が間違いだった。 構造はほぼ最適化の余地がなく(標準に寄せるのが正解)、効いたのは規約・制約・レビューというプロセス層でした。新しい記法を探していたけれど、必要だったのは「AIの仕事を制約して、見えるようにする」運用だった。

もう一つ。この検討中、AIに「検証して」と頼んだのに、AIが勝手に修正まで進めて、変更が積み上がって追えなくなった瞬間がありました。まさに認知負債。そこから「検証と修正は分ける」を自分のルールにしました。AIを速くするより、AIのミスが見えて・安く直せる状態を作る方が、ずっと効きます。

AICSS
スポンサーリンク
シェアする
小暮 哲也をフォローする
スポンサーリンク

コメント

タイトルとURLをコピーしました