チェック済みチェックボックスを :has() で親装飾
CSS の :has() 親セレクタを使い、チェックボックスが checked のときに親 label の背景・文字色・打ち消し線を動的変更する実装。JavaScript 不要。Chrome / Safari / Edge 対応。
解説
チェック済みチェックボックスを :has() で親装飾は、便利系カテゴリの「has-selector」に分類される実装パターンです。CSS のみで構成され、難易度はシンプルレベル。
2023 年以降、すべての主要ブラウザで利用可能になった :has() セレクタを活用した実装サンプルです。これまで :checked + label のような兄弟セレクタでしか実現できなかった「子要素の状態に応じて親要素のスタイルを変える」処理が、:has() によって直感的に書けるようになりました。
このスニペットは ToDo リスト風の UI で、チェック済みの項目だけ背景色・打ち消し線・色味を変える実装です。完全に CSS のみで動作するため、SPA・WordPress・どんな環境でも貼り付けるだけで動きます。
仕組み
下記コードタブから HTML / CSS をそれぞれ確認・コピーできます。プレビュー領域では実際の動作をその場で確認可能です。
CSS プロパティだけで完結しているため、フレームワーク非依存・軽量に組み込めます。React / Vue / Astro / 静的 HTML どれにも持ち込み可能です。
注意点 / カスタマイズ時のポイント
:has() は Chrome / Safari / Edge 105 以降、Firefox 121 以降でサポートされています(Firefox は 2023 年 12 月から)。IE 11 や古い Firefox では動作しないため、レガシー対応が必要な案件では JS フォールバックを併用してください。
パフォーマンス面では、:has() は親方向の再評価が走るため、深い DOM ツリーで多用すると影響が出ることがあります。リスト 100 件程度であれば実用上問題ありません。
よくある質問
IE 11 でも動きますか?
input:checked + label パターンか JavaScript で代替する必要があります。ラベルの中にチェックボックスがない構造でも使えますか?
:has() は子孫要素を任意に指定できるので、<li> や <div> の中にチェックボックスがある構造でも、セレクタを li:has(input:checked) 等に変えれば動きます。このスニペットは商用利用できますか?
そのまま貼り付ければ動きますか?
ブラウザ対応は?
Tailwind CSS でも実装できますか?
@apply や arbitrary values が必要な場合があります。