世界を動かす技術を、日本語で。

このウェブサイトにはクラスがありません

概要

  • CSSリセットの存在を否定し、 要素自体のデフォルト活用 を推奨
  • クラス排除 に挑戦し、HTMLタグやカスタム属性でスタイリングを管理
  • セマンティックなマークアップ とアクセシビリティの向上
  • コンテキストスタイルやカスタム要素利用のメリット・課題
  • 大規模プロジェクトへの適用には慎重な検討が必要

CSSリセットという幻想と、要素本来の力

  • CSSリセットは 万能ではない という認識
  • ブラウザ組み込み要素 を「カスタム要素の“カスタム”抜き」と捉える視点
  • 要素本来のデフォルト を積極活用する設計思想

クラス排除への挑戦

  • クラス完全廃止 のためのサイトリファクタリングを実施
  • CSS Zen Garden時代 以来のクラスレスアプローチへの回帰
  • 現代HTML/CSS での制約が創造性を刺激

スタイル構造とその見直し

  • CSSは base, components, utilities の3レイヤー構成
    • base:タグセレクタ中心
    • components:クラス依存を廃止し要素や属性で管理
    • utilities:完全削除
  • セマンティック要素 の利用増加
  • 共通パターン抽出 による要素デフォルトの強化
  • コンテキストスタイル (入れ子や:where(), :has()等)の活用

コンテキストスタイルの落とし穴

  • 過剰なコンテキスト指定で セレクタが複雑化
  • 例:li:has( > a + p) のような 深い入れ子と複雑な条件
  • 可読性・保守性 の低下リスク

カスタム要素と属性による新たなパターン

  • Web Components的発想 でカスタム要素名・属性を活用
  • BEMのmodifier的用途 もカスタム属性で置換可能
  • 例:note-pad, random-pattern などの カスタムタグ と属性
    • [shape-type="1"] などでバリエーション管理
  • data-属性以外の 任意のダッシュ区切り属性 も利用可能

クラス再発明の議論とその違い

  • 「クラスの再発明」との指摘もあるが
    • カスタム要素名+属性 は将来Web Components化も容易
    • タグと属性の組み合わせ で一貫したシステム形成

メリットと課題

  • CSS量削減( 全体で約5KB に)
  • アクセシビリティ向上クリーンなマークアップ
  • 著者側の設計・計画負担 は増加
  • 大規模・多人数開発では 推奨しづらい
  • セマンティック価値喪失や余計なラッパー の問題も

今後の展望と葛藤

  • 個人サイトには満足 だが、万能解ではないという認識
  • クラスの有用性に 疑問を持ち始めた 心境の変化
  • 今後の制作スタイルに 長期的な影響 を及ぼす予感

例外事項

  • 11tyのシンタックスハイライト のみクラス利用を継続
    • クライアントサイドJS導入や著者体験の悪化を避けるため
    • 100%クラスレス化は未達成

このアプローチは HTMLタグと属性の本来の力 を最大限に引き出し、 CSS設計思想の再考 を促すものです。しかし、 全てのプロジェクトに適用できる万能策ではない ことも明らかです。

Hackerたちの意見

かなりの量のCSSを削除したよ(今はサイト全体で約5KBのCSS)。これはその記事の単一ページのサイズの約2%で、特にウェブサイトのメンテナンスや追加を考えると、ほんとに些細な量だね。

5KBはほんとに些細なことだね。実際にどれくらい削除されたかは言ってないし、もしかしたら200KBかも?誰にもわからないよね。

確かに、そのページは2つの巨大なフォントを読み込んでるね。多くのブログはシステムフォントを使ってるから、サイトのサイズを減らしたいならこのアドバイスは一般的に役立つよ。フォントなしでの合計ペイロードは約12kbだから、CSSを5kbに減らすのはかなり大きなことだよ。フォントがなければ、サイト全体は最初のTCPパケットで配信できるかも。

CSSファイルで「public,max-age=0,must-revalidate」をやってなかったら、さらに無関係になってたね。

最近、アプリのフロントエンドを作るために似たような道を辿ったんだ。最初はうまくいって、CSSの最近のアップデートについてたくさん学んだよ。ほんと、進化したよね。カスケードレイヤー、ネスティング、:hasセレクタがあれば、ビューの書き方が劇的に良くなる。ブログや独特なドキュメント感のあるアプリにはいい解決策だけど、それ以上のことには制限が多くて脆いと感じた。やっぱりコンポーネントとTailwindに戻るよ。

CSSが制限が多すぎるって文句を言ってる人は聞いたことがないよ。むしろ逆だと思う。

このコメント、全然理解できないんだけど。CSSが制限的だって言ってるのに、クラスを使ってCSSを適用するだけのTailwindが解放的だって?Tailwindは実際、もっといろんなことを複雑にするよ。例えば、バリアントを指定しなきゃいけないとき、tw-variantsをインストールして、いろんなボタンを作るためにJavaScriptを書く羽目になる。shadcn-uiみたいな大きなコンポーネントライブラリにはいいかもしれないけど、シンプルさを求めるなら、button .errorやbutton .secondaryみたいな純粋なCSSの方がいいと思う。 (もちろん、あのブロックの中で@applyを使えばいいってのは分かってるけど、そうするとTailwindのメリットって何なの?)

Tailwindの炎上戦争に自分から飛び込んじゃったみたいだ。もっと考えるべきだったな。TW+TSXは、俺にとってUIを書く最も生産的な方法で、もう5年もそうしてる。気に入らないなら使わなければいいけど、お願いだから放っておいてくれ。

まあ、HTMLは典型的なドキュメントを記述するための一般的な言語であるべきだったんだ。ほとんどのウェブサイトはデフォルトの要素以上は必要ないよね。外から見ると、ウェブ開発者がウェブサイトを複雑にすることと、シンプルな原則を再発見することの間で行ったり来たりしているのが不思議だよ。

ごめん、でも複雑さを求めてるのは開発者じゃないよ。ユーザーやデザイナーは、たくさんのアニメーションで「雰囲気」を出すために、スナッピーなインタラクティブUIを求めてる。開発者は、2003年からそのまま出てきたようなウェブサイトでも全然大丈夫だと思うよ(今まで見てきた言語のドキュメントページを考えるとね)。

右クリック -> ソースを表示。見つけた "<span class=..." — え?ページを読んでみて。フッターには「99%までしか行けなかった。11tyの構文ハイライトプラグインを使っていて、スタイリングにはクラスを使ってる。」って書いてある。

それは妥当だと思う。セマンティック情報ではないし(ある意味ではそうかもしれないけど、スクリーンリーダーにそう表示させたくはないよね)、だからクラスはそこで問題ないよ。

うん、そのタイトルは馬鹿げてる。ページには175個の"class=..."属性があるよ。

何年か前にこのアプローチを試したことがあるけど、今ではアンチパターンだと思ってる。ウェブサイトやドキュメントの見た目が構造に依存するのは本当に良くない。li:has( > a + p)みたいなものは最初は賢いと思うけど、結局ボタンやアイコン、全体を包むラッパーが必要になったりする。しかもそれがリストの一つのアイテムだけのために。結局、すべてのシナリオをカバーするゴチャゴチャのCSSになったり、クラスに戻ったりする。カスタム属性の潜在的な有用性は分かるけど、クラスよりもどう良いのかはまだ完全には分からない。[shape-type="1"]の利点は.shape-type-1に対して何なの?

中間地点はないの?クラスレスのクリーンなアプローチが大好きなんだ。ドキュメントには構造があって、CSSを入れ替えるだけで簡単に変更できるのはいいよね。でも、本当に構造を壊す必要があるときだけクラスを追加すればいいんじゃない?私にとっての中間地点は、理にかなった範囲でクラスを避けることだと思う。できるだけ例外を少なくしたい。これはゴムバンドをメートルで売ってるようなものだって分かってるけど。反対側にはTailwind CSSがある。多くの人がそれを気に入っていて、開発のスピードがいいって言ってるのは知ってる。でも、私はそれが冗長すぎて「その日のフレームワーク」みたいに感じる。だから、私にとっては頭が痛くなるまではクラスレスで行くよ。その後は、仕事を進めるためにクラスをちょっと使うかな。

各ページは、異なるレイアウトや構成に合わせて、それぞれのインラインスタイルを簡単に持てるよね。静的ジェネレーターやウェブアプリでこういう風に実装したことがあるけど、めっちゃ簡単だったし、すごく速いんだよね。

たぶん、パターンを適用する文脈によると思う。この投稿はブログサイトだし、各記事は静的なドキュメントだから、一般的には特に変わった構造にはならないよね。例えば、ページには「ボタン」が一つだけある。ここではすごくうまく機能すると思うよ。

なんで見た目が構造に依存すべきじゃないと思うのか気になるな。構造に依存するのはちょっと制約があるかもしれないけど、ブラウザの大半の構造的なアイテムは、物事がどう見えるべきかのために特に存在してるんじゃないかな?記事の最後の告白は正しいと思う。これはサイトの作者に多くを求めることになる。でも、記事も言ってる通り、このスタイルは競合するアイデアよりもアクセシビリティがずっと良いんだ。サブスタックみたいなDIVが多いスタイルと比べてみて。

[削除済み]

そうだね、ドキュメント構造にすごく厳しいネスティングルールを強制しなきゃいけないから、実用的じゃないよね。特に複雑なマルチユーザーのウェブアプリでは。クラスは柔軟性と原子性を提供するし。 > [shape-type="1"] の利点は .shape-type-1 に比べて何なの?CSSセレクタのパフォーマンスの観点から見ると、クラスの方がカスタム属性よりも速いことが多いから、この特定のユースケースでは利点があるのか分からないな。

20年前に「CSS zen」と「セマンティックCSS」の悪い時代にこれを試したことがあるけど、失敗したのはHTMLの構造とプレゼンテーションを完全に結びつけることはできないからだよ。通常、HTMLが表現できる以上に複雑なスタイルやビジュアルが必要になるし、それを説明するためにセレクターやHTMLの階層を考えるのはすぐに難しくなる。それに、デザインが進化する中で、単一のウェブアプリケーションで複数のスタイルシステムをサポートする必要があることが多い。そうしないと、変更する際に全てか無かのロールアウトになっちゃう。昔のエンジニアじゃない人たちが、現代のフロントエンドシステムが提供する抽象化を見て、それが本当に必要なのか疑問に思うのはよくあること。それは健全だよ。でも、それがただの偽りや歴史的な理由で作られたものだと決めつけて、商業プロジェクトのためにみんなに放棄させようとするのは健全じゃない。

馬車の前に馬を置いてるって感じで、セマンティックCSSを完全に誤解してるよ。スタイリングはコンテンツを改善するためにあるべきで、コンテンツ自体は基本的にスタイリングなしでも成り立つべきだよ。セマンティックCSSの目的は、プレゼンテーションをあまり考慮せずにHTMLを書くことなんだ。HTMLは人間が読めるデータを構造化するだけで、この段階では見た目のことは考えない。構造化されたデータのスタイリングは後から来る。CSSを書いてその構造化データを見栄え良くするけど、その過程でHTMLには手を触れないのが理想だよ。スタイリングはただの飾りに過ぎない。これが好まれなくなったのは、みんなが質のあるコンテンツよりも派手さを気にするようになったからで、実際のページを作ることに考えを巡らせたくなかったんだよね。これは現代のウェブ全体の病の症状だと思う。今のCSSなら、これが実現しやすくなってるから、復活を願ってるよ。

20年前のCSSは、今みたいな力はなかったよ。:hasや:where、サブグリッド、他にも構造とスタイリングを効果的に切り離すためのツールがなかったんだ。時代は変わったし、以前強いられた変更を戻すチャンスがあるかどうかを評価する価値があると思う。

2000年から2015年までフロントエンドの仕事をたくさんやってたけど、今はほぼ完全にバックエンドに転向しちゃった。でも、まだ楽しんでるし、追いつこうと頑張ってるよ。最近は「アプリ」って呼んでるCSSパターンを使って開発したSPAのサイドプロジェクトがあるんだ。基本的にJSの「コントローラー」があって、各コントローラータイプにはルートHTML要素がある。要素のタイプを選んで、これらのルート要素には自動的に"{controller}--app"みたいなCSSクラスが付くんだ。その中では、ほとんどクラスなしのHTMLを使って、ほぼ全てを直接の祖先「>」オペレーターに基づいてスタイリングしてる。例えば、.sidebar--app { > ul > li > a { // サイドバーのスタイル } } って感じで、一般的に「コントローラー」のスコープはかなり小さくて、せいぜい数要素深い程度にしてる。これは一種の階層的MVCで、コントローラーの中にさらにコントローラーがいる感じ。例えば、サイドバーコントローラーの中に検索コントローラーがあるんだ。検索コントローラーは自分の要素を管理して、イベントで変更を報告するだけ。こういうパターンのおかげで、JSとCSSはすごくクリーンで理解しやすくなって、生成されたHTMLもきれいなんだ。これに近いことを10年近くやってるけど、楽しいサイドプロジェクトだよ。スコープは結構大きいけど、正直言って取り組むのが楽しい。全てのスタイリングはかなりスコープが狭いから、予期しない問題もほとんどないし、実際のHTMLも読みやすくて心地いいよ。

もっと良い言い方は「DIVの数を減らす/排除する」だと思う。実際の問題は、一般的なDIVが過剰に使われていることだよ。すでに存在するHTML要素が、意図した使い方にぴったりなのにね。HEADERやFOOTER、NAV、Pをほとんど見かけないのは、みんなが一般的なDIVタグを使っちゃうからだよ。https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/...

BEMのようなクラスが大規模で複雑なサイトにはまだ最適なアプローチだと自信を持って言えるよ。.block__element--modifierパターンを守る限り、.block__element__secondelementのようなクラスは作らないし、ネストや子孫セレクター、:has()は可能な限り避けるべきだよ。カスタムタグを使うと、前述の問題が必ず発生するし、ブラウザはスタイルを正しくターゲットにするために余分なDOMトラバーサルをしなきゃいけなくなる。BEMならそうじゃない。クラスセレクターのフラットなリストが要素にきれいにマッピングされるから、ブラウザがHTMLをDOMにパースする時、すべての子孫がパースされるのを待つ必要がないし(:has()が機能するために)、ネストや子孫セレクターに現在のDOMパスが一致するかどうかを確認するための余分なチェックもいらない。どんどんパースしてレンダリングを続けられるんだ。これが違いを感じないかもしれないけど、古いデバイスを使ってる人には、瞬時とちょっともたつくの違いが出るよ。

それにしても、このマークアップ見てよ。めっちゃクリーンで、ピカピカだね。これがこの執着的なビットいじりの本質なんだろうけど、無関係な見た目ばっかり。機能面は他の人も指摘してる通り、ひどいことになってる。ページの構造にスタイルを固定しちゃって、要素を移動させるためにCSSを構造的に変更しなきゃいけないなんて。

そうそう。「わぁ、このマークアップめっちゃ綺麗!」なんて見たくないんだよね。「これ、柔軟で、全部やり直さなくても簡単に変更できるよ!」ってのが見たい。変化について話してないなら、他のことは無意味だよ。