JavaScriptのパララックスがいつも少しおかしく見える理由があります — ちょっとずれていて、レイヤーがページの半フレーム遅れで泳いでいるような感じ。雑なコードではありません。スクロールイベントがブラウザがすでに描画した後にJavaScriptに届くからです。ブラウザはこれをかつて解決しました — 粘着的なヘッダーをposition: stickyに変えた時に。Scroll-driven animationsは同じ手法を、すべてのスクロールに連動したエフェクトに一度に適用したものです。
10年間、サムネイルをヒーロー画像にアニメーションさせるには一つの技法しかなかった:前後の位置を測定し、transformでその差を偽り、再生する。FLIP。すべてのアニメーションライブラリがそれを行い、すべてが最悪のタイミングでメインスレッドのJavaScriptという代償を払ってきた。View Transitions APIはそのトリック全体をブラウザに移し、React 19.2とNext.js 16以降、契約全体はnameという一つのpropだけになった。
千件のコメントを含むリストのレンダリングが遅いので react-window に手を伸ばす——すると、なめらかなスクロールと引き換えに、Ctrl+F、ページの印刷、そしてスクリーンリーダーのナビゲーションの一部を失うことになる。表示ウィンドウの外にある要素が、DOMから物理的に存在しなくなってしまうからだ。content-visibility はまったく別の角度から同じパフォーマンス問題を解決する。要素はDOMに残ったままで、ブラウザはただ、要素が表示領域の近くに来るまで、レイアウトや描画といったコストの高い処理をその要素に対して省略するだけだ。そして驚くべきことに、テキストを検索したときには一時的にその要素を『見える状態』に戻すことさえできる。
アクセシビリティの記事で取り上げた、`display: none`で隠されているのにアクセシビリティツリーには残り続けていたモーダルは、divをゼロから組み立ててモーダルを作ることに起因するミスの一例でした。本当に問うべきなのは、そもそもなぜゼロから作らなければならなかったのか、ということです。ネイティブな`<dialog>`とpopover属性が無料で提供してくれるもの——top layer、フォーカストラップ、light dismiss——を確認し、この二つの仕組みがどこでどれほど違うのか、その違いを取り違えることがいかに簡単にアクセシビリティを欠いたインターフェースへの近道になるかを見ていきます。
ユーティリティクラス`.mt-4`は、論理的には後から追加された分勝つはずなのに、`.card .card__header .card__title`というルールに負けてしまいます。これは偶然ではなく、詳細度が設計通りの仕事をしているだけです。`@layer`は、詳細度と一緒にではなく、その手前で働くまったく新しい対立解決の軸を導入します——そして、ネット上のドキュメントの一部さえ誤って説明してしまうほど直感に反する落とし穴が一つあります。
フォームのフィールドは、中のinputが不正な値のとき赤くハイライトされるべきである。単純な話に思えるが、CSSは25年もの間、要素に対してその内側で何が起きているかを問い合わせる方法を持たず、その逆しかできなかった。:has()がこの方向をどう逆転させるのか、通常のコンビネータとどう違うのか、そしてこの新しい力が実際にパフォーマンス上のコストを伴う場面はどこかを見ていく。