- 最近のWebサイトの性能低下の主因は、過剰なJavaScriptの使用とトラッキングスクリプトであり、多くの場合はHTML/CSSだけでも十分に置き換え可能
- CSSネスト、相対色、新しいビューポート単位(lvh, svh, dvh) など最近追加された機能により、以前はJSやプリプロセッサに依存していた作業を簡単に解決できるようになった
- CSSは単なるスタイルツールではなく、アニメーション、入力検証、ダークモードのテーマ、アコーディオンメニュー まで実装できる強力な言語である
- 性能面でもCSSはGPUアクセラレーションと別スレッドで動作し、アニメーションやトランジションでJSより滑らかで効率的 である
- 筆者はCSSを単なる実用ツールではなく、表現と芸術の手段 として強調し、Web開発者がモダンCSSの可能性をもっと活用することを勧めている
序論: Webの複雑さ、そして新しい試み
- 多くのWebサイトがJavaScriptフレームワークの過剰使用によって性能低下と複雑化に悩まされている
- Reactアプリは読み込みに数秒かかり、NextJSはハイドレーションエラーを発生させる
node_modules フォルダは数GBの容量を占める
- JavaScriptがなくてもHTMLとCSSだけで強力な機能を実装できる
- ECサイトの複雑なカートやダッシュボード以外では、JavaScriptが必須ではない場合もある
- この記事はCSSの最新機能を紹介し、開発者がJavaScriptだけに依存せず多様な可能性を探るよう促している
CSSに対する誤解と認識
CSSは本当に難しくて不便なのか?
- CSSに対する否定的な認識は、基礎学習の不足に由来する
- 多くの開発者はCSSの基礎を飛ばして、JavaScriptやTypeScriptに集中している
- CSSは単なるスタイリングツールではなく、ドメイン特化言語として強力な機能を提供する
- CSSは**フレックスボックス(flexbox)**のようなツールで複雑なレイアウトを簡単に実装できる
- 例:
display: flex と justify-content: center でdivの中央揃えが簡単
- ブラウザの開発者ツールは、フレックスボックスのプロパティを視覚的に調整できるウィジェットを提供する
- 一方(例: JS)だけを深く掘り下げてCSSをおろそかにすれば、負担が大きくなるのは当然である
CSSを書く苦痛、そして変化
- 昔のCSSはあまり快適ではなかったため、SassやTailwindのようなツールが登場した
- 例:
.post > .buttons .like:hover のような長いセレクタチェーンを管理しなければならなかった
- 最近は品質改善機能(ネストなど)が追加され、素のCSSだけでも快適に開発できるようになった
- CSSネスト(nesting) は関連スタイルを1か所にまとめ、可読性を高める
- 例:
.post { & > .buttons { .like { &:hover { ... } } } }
- 親子関係が明確になり、短くシンプルなクラス名を使える
- 相対色(relative colors) は色調整を容易にする
hsl(from #123456 h s calc(l + 10)) で明るさを調整できる
color-mix() で2色を混ぜて動的な色を作れる
- メディアクエリの範囲構文 により、
(width <= 768px) のように直感的な条件設定が可能
- lh単位 は行の高さに合わせたスタイリングをサポートする
- scrollbar-gutter プロパティは、スクロールバーによるレイアウトシフトの問題を解決する
- Baseline は主要ブラウザでの機能互換性を保証する
- newly available は最新ブラウザで動作する
- widely available は2.5年前のブラウザまでサポートする
- 例: CSSネストは2023年12月からすべてのブラウザでサポートされている
なぜCSS/HTMLだけで開発するのか?
- 一部のユーザーはJavaScriptをデフォルトで無効化している(セキュリティ、プライバシー保護などの理由)
- 純粋なCSS/HTMLだけでWebサイトを提供すれば、こうしたユーザーもサイトを利用できる可能性が高まる
- 開発側・利用側の両面で、CSS/HTMLだけを使うことには速度、アクセシビリティ、CPU/バッテリー使用の面で利点が大きい
- CSSアニメーションはコンポジタスレッドで実行され、CPU負荷を減らす
- JavaScriptはイベントループを通じて実行されるため、わずかな遅延が生じうる
- アクセシビリティと使いやすさも向上する
- ボタンのホバー効果、トーストアニメーション、入力検証などはCSSで簡単に実装できる
CSSの実用的な例と主な機能
@starting-styleで自然な開始アニメーションを実装
- 以前は要素の登場アニメーションを実装するために、keyframesやJSトリガーなど複雑な構造が必要だった
- @starting-style の導入で開始状態の指定が簡単になった。要素の初期状態アニメーション(例: フェードイン)を容易に実装できる
transition: opacity 1s; @starting-style { opacity: 0; } のように設定
- 別途
@keyframes やJavaScriptがなくても動作する
- transitionとともに初期状態を明示するだけで、自然にアニメーションが適用される
- 例: トーストメッセージの透明度や位置の切り替えを滑らかに処理
ダーク/ライトモードの簡単なテーマ設定
- color-scheme: light dark は、ユーザーの設定に応じてテーマを自動で切り替える
- light-dark(#000, #FFF) 関数は、ライト/ダークモードに合った色を指定する
- ラジオボタンと**:has**セレクタで、ユーザーによるテーマ選択をサポートする
- JavaScriptなしでCSSだけでテーマ切り替えが可能
- 必要に応じてJavaScriptでテーマ保存/読み込みを追加できる
ラジオ/チェックボックスと :has, :checked などでカスタムUIを生成
- タブ、アコーディオン、トグルなど複雑なインタラクションもJavaScriptなしで実装可能
- ラジオボタン は :checked と :has でカスタムスタイリングできる
- 例:
label:has(input:checked) で選択されたボタンのスタイルを指定
opacity: 0 で入力要素を隠しつつ、スクリーンリーダーのアクセシビリティは維持する
- details要素 はFAQのようなアコーディオンメニューの実装に適している
name 属性で単一オープン状態を制御できる
[open] 状態に応じてアニメーションを追加できる
入力検証と状態反映
pattern、required などのHTML属性と、CSS疑似クラス(:valid, :invalid, :user-valid など)を組み合わせることで、リアルタイム検証と視覚的フィードバックを提供できる
- 入力フィールドのoutline/borderスタイル変更などでユーザー体験を向上できる
- HTMLのpattern属性で入力フィールドの妥当性を検証する
- 例:
\w{3,16} で3〜16文字の英数字またはアンダースコアを許可
- CSSの**:valid** と :invalid で妥当性に応じてスタイリングする
- :user-valid と :user-invalid は、ユーザーが入力した後にのみスタイルを適用する
- :has セレクタにより、入力状態に応じて別要素をスタイリングできる
- 一部の場合(例: 複雑な入力条件)ではJSが必要だが、大半はCSS/HTMLで十分である
ビューポート単位の正しい使い方
vw/vh 単位はモバイルでアドレスバー(ナビゲーションバー)の表示/非表示に応じて精度の問題が発生する
- lvh/svh/dvh(largest/smallest/dynamic viewport height)など新しいビューポート単位の使用が推奨される
- lvh: 全画面用(例: 全画面背景)
- svh: 常に画面に見えている必要があるボタンやリンクなどに活用
- dvh: スクロールなどの変化に応じて動的にサイズを割り当てる
- キーボードオーバーレイは interactive-widget 属性や VirtualKeyboard API で処理する
<meta name="viewport" content="width=device-width, interactive-widget=resizes-content">
- Chromium系ブラウザでは
navigator.virtualKeyboard.overlaysContent = true
CSSウィッシュリスト(惜しい点・欲しい機能)
- 再利用可能なブロック: クラス内で別のクラスを適用(例:
@apply border)
- 結合されたメディアクエリセレクタ:
@media とクラスセレクタの結合
- nth-child変数:
span { --nth: nth-child(); } による動的スタイリング
- nth-letterセレクタ: 特定の文字をスタイリング(例:
p::nth-letter(2))
- 単位の除去:
calc(100vw / 1px) で単位なしの値を生成
- image()関数: 代替色と画像断片のサポート
- body内のstyleタグ: 公式標準サポートによるFOUC問題の緩和
まとめ: CSS、そしてWebの芸術性
- CSSは単なるツールではなく、創造的表現の手段である
- AIツール やビルドチェーン(リンター、minifyツール)は創造性を制限しうる
- CSSは性能、アクセシビリティ、芸術的表現を同時に満たす
- この記事は約49kBのJavaScriptなしのHTML/CSSで書かれている
- すべてのインタラクティブなウィジェットと視覚要素は手作業で実装されている
- 例: CSSクリックゲーム は、CSSのプログラミング言語としての可能性を証明している
3件のコメント
フルスタックだったのですが、やはりキャリアが上に進むほどFEをやる機会がなくなり、10年ほど触っていませんでした。最近、ある企業で講義をする機会があって、軽く紹介するついでに見てみたのですが、本当に驚くほど変わっていましたね。scssまで合わせるとさらに便利でした。とはいえ、このCSSの領域は実に不思議です。学ぶのは簡単ですが、評価されるほど上手く使えるかどうかは、個人の美的センスや創造力によって分かれると思います。ユーザビリティやデザインがより重視されるウェブの時代に、パブリッシャーの価値がもっと高く評価されていないように思えて残念です。
今回、Web開発技術を少しかじる趣味活動として、基礎1つないまま手探りで
nextjs、authjs、tailwind、shadcnを使って基本的な掲示板を作ってみたのですが……学習難易度が最大だったのは CSS でしたね。Hacker Newsの意見
今回CSSに追加されたネスト機能はありがたいが、全体として見るとCSSは本当に奇妙で、個人的にはひどい言語だと思う。自分がうまく使えていないせいかもしれないが、あまりに複雑で雑然としていて、意味不明なルーン文字をあちこちに移して試しているような感覚になる。スタイリングとレイアウトの仕組みが混ざっているうえ、継承と包含の関係も違うので余計に混乱する。スタイリングとレイアウトを一緒にしたのは間違いだったと思う。すでに根本的に壊れているシステムに機能を足すだけで解決できるとは思えない
gapプロパティがflexとgridで異なる動きをすることが挙げられる(リンク)。レイアウトを一度作ると実質的にほぼ固定され、複雑なネイティブまたはJSベースのカプセル化なしには柔軟に変えにくい。そうすると予期せずフォントの太さが変わったり、モバイル用メニューがデスクトップにも出てきたりするcalcなどを使って、より整理されたレイアウトシステムを数学的に実装することもできそうだ。今のプリプロセッサ言語は、CSSの中ですでに未完成な概念の上に、また未完成な機能を貼り付けているだけなので、むしろさらに混乱するCSSの最悪なところは、多くの人がろくに学びもせず、1日ほど無理やり使っただけで強い意見を持つことだと思う
.foo > .bar:nth-child(2n) ~ .bazみたいなコードになる。そうするとまた同僚のコードが壊れる。単純なレイアウト一つでも頭が痛い。最近はだいぶ良くなったとはいえ、そもそもこういうカスケード中心の構造が問題だと思う。構文など他の批判は些細だ。実用的で簡単に使えるなら構文は許容できるが、CSSはそうではなかった。Webレイアウト作成が職業になってはいけないと思うこの文での「一部のユーザーはJavaScriptを望まない」という根拠は、あまり腑に落ちない。私もArchユーザーで各種スクリプティングやクローリングに熱心な人間だが、「NoScript」環境に注力することは特に重要だとは感じない。これはごく少数の嗜好なので、大抵は無視してよいと思う。「10%がIE6を使っている」と言っていた時代に近い感覚だ。それでもCSSがより優れている理由は他にもたくさんあると思う。いずれにせよ、これは主要な争点ではないが、全体の流れとしてはそういう印象を受けるという意見だ
ネストがもう正式標準になっていたとは知らなかった。つい最近まで提案段階だと思っていた。CSSには奇妙な点も多いが、JavaScriptのようにだんだんマシな言語へ進化している流れは感じる。Flexbox、
:hasセレクタ、ネストのおかげで、昔からの多くの痛点がかなり解消されたウィッシュリストにあったCSS機能のうち二つは、すでに仕様に存在している
sibling-index()とsibling-count()で実装可能(MDN説明)@functionと@mixinのドラフト仕様にある(仕様ドラフト、CSS Tricksの説明)CSSの文法はひどいと思う。私は10〜15個の言語を扱うが、CSSがいちばん読みにくく理解しにくい。x86アセンブリよりも難解だ。CSSはレンダラーのための事前トークン化された入力だが、トークンでもないし、人間が書くには妙だ。RFCのASN.1のように、「こうしてはいけない」という反面教師として使うべきだと思う
font-size: 12pxのようなコードは十分人間にとって読みやすいのに、なぜ難しいと感じるのか理解できない。私には本当に単純に見えるラジオタブの例がアクセシビリティ面で問題ないのか気になる。WAI-ARIAの基準では、
aria-selected、tabindex、aria-controls属性はタブが切り替わるたびにJSで更新すべきだったと思うが、確信はない。アクセシビリティはしばしば後回しにされる。HTML/CSSだけ使えば自動的にアクセシブルになると誤解することもある。アプローチを選ぶときに、もう一度考慮すべき点だJSなしでもこういうインタラクティブな効果は実装できる(サンプルページ)
10年目のWeb開発者として、こういう記事は私たちの確信を揺さぶる必要があると感じる。タイトルはいまいちで、危うく読み飛ばすところだった。ちなみにCSSだけで地図レンダリングはできない
Vegaという名前のせいで先入観を持つ人もいるかもしれないが、このサイトは本当に気に入っている。全体的なデザインも良いし、このページの内容も本当に素晴らしい。今後Web開発をする人たちにはぜひリンクを共有したい。arruptedもとても好きで、以前すごい成果物を作っていた。だから今回、見慣れたドメインをメインに見かけてうれしい