カランのブログ

ソフトウェアエンジニア / 台湾人 / 福岡生活

今のモード ライト

近年、CSSには多くの擬似クラスが追加され、過去とは異なり、ほんの一部のブラウザだけで実装されているわけではありません。今日はいくつかのCSS擬似クラスを紹介し、実際の例を通じてレイアウトをサポートします。

  • :is
  • :where
  • :has
  • :lang
  • :focus-within
  • :first-child:last-child

:is

以前、複数のセレクタに同じCSSルールを適用するには、以下のように書いていました。

.a-class,
.b-class {
  font-size: 25px;
}

これに問題はありませんが、:isを使用すると、次のように宣言を簡略化できます。

:is(.a-class, .b-class) {
  font-size: 25px;
}

セレクタを適用する必要がある場合、:isを使用すると読みやすくなります。まだWorking Draftの段階ですが、Can I useのデータによると、98.1%のユーザーが使用できます。

単一のクラスだけでなく、他のセレクタと組み合わせることもできます。

:is(.a-class, .b-class) a:hover {
  opacity: 0.8;
}

:where

:where:isと同じ機能を持っていますが、優先順位に違いがあります。:whereを使用すると、優先順位は*と同じになります。しかし、:isは異なり、リスト内の最も高い優先順位に基づいて最終的な優先順位が決まります。

この例では、#pageがあるため、クラスセレクタよりも優先順位が高いため、最終的な色は赤になります。:whereを使用する場合、セレクタに追加の優先順位はありません。

そのため、最終的な色は黄色になります。 上記の結果から、使用シーンは次のように分けられます。

  • :where()を使用してグローバルスタイル(リセットなど)を作成し、変更が必要な場合は直接上書きできるようにする。
  • :is()を使用して複数のセレクタに対してローカルスタイルを適用し、すべてのセレクタに同じ優先順位が適用されることを保証する。

:has

:hasは、条件に一致する子要素が存在する場合に親要素に一致します。説明は少しややこしいですが、例を使うとわかりやすいです。便利なシーンの一つは、「子要素がフォーカスされたときに親要素のスタイルを変更したい」というものです。 検索機能を実装する場合、検索アイコンを入力フィールドの横に配置することがあります。入力フィールドがフォーカスされたとき、単に入力フィールドにフォーカスのスタイルを適用したいだけでなく、アイコンを含む入力フィールド全体にフォーカスのスタイルを適用したい場合があります。この場合、input:focusでは望む効果を得ることができません。 以前の解決策は、CSSセレクタが有効になるようにDOMの構造を変更するか、JavaScriptでフォーカスイベントを監視し、親要素にフォーカスがあることを伝えるためのクラスを追加する方法でした。しかし、:hasを使用することで、構造を変更する必要なくCSS内で直接実現できます。

これにより、inputがフォーカスされたとき、.form:has(input:focus)が有効になり、スタイルが親要素に適用されます。"子要素が条件を満たす場合に親要素を一致させる"ということは、フロントエンド開発者の長い間の願いであり、これで大きな前進が実現されました。 :hasには他の使用方法もありますが、特に「子要素が特定の条件に一致する場合にこのセレクタを適用する」シーンで使用します。

たとえば、テーマを切り替える場合、body:has(input[type="checkbox"]:checked)を使用すると、JavaScriptを使用せずに色のテーマを切り替えることができ、適切なDOM構造を保持できます。

:hasの使用シーンについては、webkitのブログにさらなる使用例があります。:hasは比較的新しい擬似クラスであり、ブラウザのサポート率はまだ高くありません(82.92%)。導入する場合は注意が必要です。

:focus-within

経験豊富なフロントエンド開発者の一部にとって、先ほどの例は実際には:focus-withinで置き換えることができることに気づいたはずです。:focus-withinは、子要素がフォーカスされたときに一致し、このため親要素のスタイルを変更することができます。 たとえば、フォーカス時にフォームにbox-shadowを追加したい場合は、次のように書くことができます。

ただし、:focus-withinはフォーカスにのみ適用でき、多様な選択肢を作成することはできません。フォーカスされていない場合に一致させる必要がある場合は、より柔軟な:hasを使用することができます。

:lang

多言語ウェブサイトを実装する際、<html>lang属性を追加して現在のウェブサイトの言語を示すことがあります。時には異なる言語ごとに異なるフォントを表示する必要がある場合、:langを使用しない場合は、次のように書く必要があります。

html[lang="zh"] p { font-family: var(--font-zh); }
html[lang="en"] p { font-family: var(--font-en); }

これは少し冗長ですが、:langを使用すると、セレクタの構文を簡略化できます。

p:lang(en) {
  font-family: var(--font-en);
}

p:lang(zh) {
  font-family: var(--font-zh);
}

:first-childと:last-child

これらは非常に一般的な擬似クラスですが、多くのフロントエンド開発者が知らないことに気付きました。これらの擬似クラスを使用すると、最初の子要素または最後の子要素を指定できます。最も一般的なシーンは、margin-rightを指定する際に最後の要素に適用したくない場合です。その場合は、次のように書くことができます。

.tab {
  margin-right: 8px;
}

.tab:last-child {
  margin-right: 0;
}

または、より簡潔にするために:notと組み合わせることもできます。

.tab:not(:last-child) {
  margin-right: 8px;
}

なぜJavaScriptを使用しないのですか?

一部のユーザーはJavaScriptを有効にしない場合があります。特にブログなど、主に静的な記事のあるウェブサイトでは、多くの読者がJavaScriptを有効にしない可能性があります。しかし、読みやすさを損なわずに読書体験を向上させたい場合、上記で紹介した擬似クラスはレイアウトの問題を解決するのに役立ちます。シンプルなものが求められるのであれば、複雑なものを使う必要はありません。

作者

Kalan 頭像照片,在淡水拍攝,淺藍背景

愷開 | Kalan

Kalan です。台湾出身で、2019年に日本へ転職し、福岡に住んでいます。フロントエンド開発に精通しているだけでなく、IoT、アプリ開発、バックエンド、電子工作などの分野にも挑戦しています。 最近、エレキギターを始めました。ブログを通じて、より多くの人と交流できればと思っています。気軽に絡んでください