HTML/CSS

CSS :has() 疑似クラスで革命的なスタイリング!JavaScriptなしでできる魔法のテクニック ✨

こんにちは、みなさん!コーダーのためのWeb制作ブログの中の人です!👋
今日は2023年辺りから話題になったWeb制作でよく使われている CSS の :has() 疑似クラスについて詳しく解説していきます。😊
初めて`:has()`に出会った時は「面白いけど使い道がいまいちよくわからず・・・🤔」
先週のプロジェクトで久しぶりに`:has()`を使ったら、改めて感動したので記事にしていきます!

この疑似クラス、実は「親セレクター」とも呼ばれていて、従来のCSSでは不可能だった「子要素の状態によって親要素をスタイリングする」ことができるんです!今まで JavaScript でしか実現できなかった表現が、CSSだけでできるようになったのは本当に革命的ですよね。💡

🤔 :has() 疑似クラスとは?

:has() 疑似クラスは、指定したセレクターにマッチする子要素や後続の兄弟要素を持つ要素を選択できる疑似クラスです。

基本的な構文はこのようになります:

/* 基本構文 */
要素:has(セレクター) {
    /* スタイル */
}

例えば、画像を含む div 要素だけにスタイルを適用したい場合:

div:has(img) {
    border: 2px solid #3b82f6;
    padding: 20px;
}

これで「画像を含む div 要素」だけが青い枠線と余白を持つようになります!🎨

🌟 :has() の便利な使用例

1. フォームの状態管理

フォームフィールドの状態によって、フォーム全体のスタイルを変更できます:

/* エラーのある入力フィールドを持つフォームグループ */
.form-group:has(input:invalid) {
    background-color: #fef2f2;
    border-left: 4px solid #ef4444;
}

/* フォーカスされた入力フィールドを持つフォームグループ */
.form-group:has(input:focus) {
    background-color: #eff6ff;
    border-left: 4px solid #3b82f6;
}

/* チェックボックスがチェックされているフォームグループ */
.form-group:has(input[type="checkbox"]:checked) {
    opacity: 0.6;
    text-decoration: line-through;
}

2. カードレイアウトの動的スタイリング

カードの内容によってレイアウトを自動調整:

/* 画像を含むカード */
.card:has(img) {
    grid-template-rows: 200px 1fr auto;
}

/* ボタンを含むカード */
.card:has(.btn) {
    border-bottom: 3px solid #10b981;
}

/* バッジを含むカード */
.card:has(.badge) {
    position: relative;
    overflow: visible;
}

3. ナビゲーションのアクティブ状態

現在のページのナビゲーション項目を持つメニュー全体のスタイリング:

/* アクティブなリンクを持つナビゲーション */
nav:has(.active) {
    background-color: #1f2937;
}

/* ドロップダウンが開いているメニュー項目 */
.menu-item:has(.dropdown:hover) {
    background-color: #374151;
}

4. ホバー効果の拡張

子要素のホバー状態で親要素も一緒に変化:

/* 画像にホバーした時、カード全体を変化 */
.card:has(img:hover) {
    transform: translateY(-5px);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}

/* リンクにホバーした時、親コンテナの背景変更 */
.content:has(a:hover) {
    background-color: #f8fafc;
}

💫 実践的な活用シーン

ショッピングカートの状態表示

/* カートにアイテムがある場合のヘッダー */
header:has(.cart-item) .cart-icon::after {
    content: '';
    position: absolute;
    top: -5px;
    right: -5px;
    width: 10px;
    height: 10px;
    background: #ef4444;
    border-radius: 50%;
}

記事の内容によるレイアウト調整

/* 動画を含む記事 */
article:has(video) {
    max-width: 800px;
}

/* コードブロックを含む記事 */
article:has(pre) {
    font-family: 'SF Mono', Monaco, monospace;
    line-height: 1.6;
}

⚠️ ブラウザ対応状況

:has() 疑似クラスの対応状況は古いブラウザやサポートが終了したブラウザを使用している場合は対応していない可能性がありますが🧑‍💻、現代の主要なウェブブラウザであれば問題なく利用できます👌✨

/* フォールバック用のスタイル */
.form-group {
    background-color: #ffffff;
}

/* :has()をサポートするブラウザ用 */
@supports selector(:has(*)) {
    .form-group:has(input:invalid) {
        background-color: #fef2f2;
        border-left: 4px solid #ef4444;
    }
}

🎯 :has() を使う時の注意点

1. パフォーマンスを考慮する

:has() は強力ですが、複雑なセレクターと組み合わせるとパフォーマンスに影響する場合があります:

/* 避ける:複雑すぎるセレクター */
div:has(div:has(div:has(span))) {
    /* ... */
}

/* 推奨:シンプルで明確なセレクター */
.container:has(.error-message) {
    /* ... */
}

2. セマンティックを意識する

:has() の便利さに頼りすぎず、HTML構造の意味を大切にしましょう:

/* 良い例:意味のあるクラス名と組み合わせ */
.notification:has(.error-icon) {
    background-color: #fef2f2;
}

🚀 今すぐ試せる実践例

以下のCodePenで :has() の動作を実際に確認できます。フォーム入力、チェックボックス、ホバー効果など、様々なインタラクションを試してみてください!

[CodePen: CSS :has() 疑似クラス デモ]

See the Pen Untitled by ひさ (@npupiwfh-the-sans) on CodePen.

🏁 まとめ::has() でCSSの可能性が広がった!

CSS :has() 疑似クラスは、従来JavaScriptでしか実現できなかった表現をCSSだけで可能にしてくれる画期的な機能です。特に以下のような場面で威力を発揮します:

  • フォームの状態管理: 入力内容によってUIを動的に変更
  • コンポーネントの状態表示: 子要素の状態を親に反映
  • インタラクティブな効果: ホバーやフォーカスの拡張
  • レイアウトの自動調整: コンテンツに応じたデザイン変更

私も最近のプロジェクトで :has() を積極的に使うようになって、JavaScriptのコード量が大幅に減りました。特にフォームのバリデーション表示やカードコンポーネントの状態管理で重宝しています!😄

💡 今後の展望

CSS :has() の普及により、今後はより宣言的でメンテナブルなスタイリングが主流になると予想されます。JavaScriptとCSSの役割分担がより明確になり、開発効率も向上するでしょう。

みなさんも :has() を使った面白いテクニックや活用事例があれば、ぜひコメント欄もしくはX(Twitter)@TumaLOVE0127 でシェアしてくださいね!新しい発見があるかもしれません。👋

hisa

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA