1659146400
CSS:has()
疑似クラスは、何年もの間最も待望されていた機能の1つです。これはレベル4のCSSセレクターであり、 Chrome 105以降で完全にサポートされる機能として利用できるようになり、他のブラウザーでもまもなく通常の機能になる可能性があります。
in CSSはリレーショナル疑似クラスであり、:has()
特定の要素に特定の子要素が含まれているかどうかを確認し、一致する要素が見つかった場合はそれを選択して、それに応じてスタイルを設定できます。
この記事では、:has()
セレクターの必要性、その一般的な使用法、単純なものから高度なものまでのさまざまなアプリケーションとユースケース、ブラウザーの互換性、およびフォールバックについて説明します。
:has()
セレクターが必要なのですか?ほとんどの開発者は、CSSがデフォルトでサポートしていない特定の機能をJavaScriptに依存しています。ただし、今日のWebブラウザーはこれまでになく強力であり、多くの新しく興味深いCSS機能への扉を開いています。
:has()
セレクターはそのような機能の1つです。子ではなく親で機能し、セレクターのコンマ区切りリストを引数として使用して、それが表す要素の子の間で一致するものを探します。その機能はjQueryhas()
メソッドに似ています。
:has()
フロントエンド開発におけるセレクターの一般的なニーズのいくつかを調べて、この機能が何年にもわたって非常に高い需要があった理由を説明しましょう。
1つは、要素に他の特定の要素が含まれているかどうかを確認し、それに応じてスタイルを設定する可能性です。あなたがここで見ることができるように、JavaScriptは以前これをする唯一の方法でした:
let content = document.querySelector("#content"),
headings = []
if(content) {
headings = content.querySelectorAll("h1, h2, h3")
}
if(headings.length) {
// do something
}
上記のコードquerySelectorAll
では、見出しの分割要素をチェックするためのWebAPIメソッドであるを使用しました。このメソッドは、指定された要素のNodeListを返します。
空のNodeListは、直接の親に要素が存在しないことを意味します。上記の実装はここにあります。または、 CSSの:has()
代替案をここで確認できます。
2つ目は、子から親要素を選択する機能です。繰り返しになりますが、そうするためのCSS機能がないため、開発者はWebAPIのparentNodeプロパティに依存しています。
let el = document.querySelector(".someElement"),
elParent = null
if(el) {
elParent = el.parentNode
}
上記のコードのCodePenデモと、セレクターがこれを実装する方法:has()
をここで表示し ます。
最後に、特定の要素の前の兄弟を選択する機能があります。CSSの兄弟セレクターを使用すると、次の兄弟を選択できますが、前の兄弟を選択するCSSのみの方法はありませんでした。JavaScriptの実装は次のようになります(CodePenのデモはこちらからご覧ください)。
let el = document.querySelector(".someElement"),
elPs = null
if(el) {
elPs = el.previousElementSibling
}
セレクターを使用してこのアクションを実行する方法については、:has()
こちらをご覧ください。
上記でJavaScriptを使用して行ったすべてのことは、CSSを使用して実現できるようになりました:has()
。Google Chromeでこの機能を有効にしてテストする方法を学習した後、次のセクションでそれらを1つずつ説明します。
:has()
古いバージョンのChrome(v.101-104)を使用している場合は、Chromeフラグからこの機能を有効にできます。Chrome 101以降を使用していることを確認し、ブラウザのアドレスバーからchrome://flagsに移動します。
Experimental Web Platformの機能を[有効]に設定すると、準備が整います。:has()
ブラウザを再起動すると、ChromeブラウザでCSSを操作できます。
:has()
セレクターは何をしますか?:has()
疑似クラス、その使用法、およびプロパティを調べてみましょう。疑似クラスであるため、コロンを使用して任意のセレクターにアタッチでき、パラメーターとしてクラス、ID、およびHTMLタグを受け入れます。
以下のコードは、その一般的な使用法と構文を説明しています。クラスは、疑似クラス.selector
を使用してパラメーターとして渡された要素が含まれている場合にのみ選択されます。has()
.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
:has()
適切と思われる場合はいつでも、複数の疑似クラスを次々にチェーンできます。以下のコードは、この連鎖がどのように機能するかを示しています。
.selector:has(div):has(.class):has(#id) {
...
}
チェーンと同様に、複数の要素セレクターのリストを提供することもできますが、はるかに効率的です。
.selector:has(div, .class, #id) {
...
}
誤って無効な要素セレクターを:has()
疑似クラスに指定したとします。それを無視して、有効なセレクターのみを検討するのは十分にインテリジェントです。
.selector:has(div, accordion, .class, ::lobster, #id) {
...
}
accordion
および::lobster
は無効なセレクターであり、上記の場合は無視されます。開発者ツールにCSSエラーやアラートは表示されません。
:has()
CSSのセレクターが役立つシナリオの例をいくつか見てみましょう。
:has()
セレクターのデフォルトの動作は、特定の要素のセットが含まれている場合に何かを選択することであるため、これはセレクターの最も一般的な使用法である可能性があります。しかし、子要素のみを認識している場合はどうなるでしょうか。
ここでは、ユニバーサルセレクター(*
):has()
と子コンビネーター(>
)を使用して、親について何も知らなくてもすばやく親を選択できます。
上記のプロパティセグメントで説明したように、:has()
複数のエンティティのリストを渡すことができます。つまり、特定の要素内で必要な数のセレクターを確認できます。
:has()
前の兄弟の選択は、CSS隣接兄弟コンビネータを疑似クラスと組み合わせることによって可能になります。
ご存知かもしれませんが、隣接する兄弟コンビネータは、特定の要素の次の兄弟を選択します。この動作をで使用しhas()
て、前の兄弟を取得できます。簡単に言えば、要素に次の兄弟がある場合、コンビネータを使用して簡単に選択でき:has()
ます+
。
:has()
セレクターを使用すると、特定の子要素がある場合とない場合のスタイリングを回避できます。キャプションのある場合とない場合のFigure要素は、ここでの完璧な例です。
figcaption
要素はあるがテキストが含まれていない場合はどうなりますか?その場合、:not
と:empty
セレクターを使用してコンテンツをチェックできます。
図の装飾と同様に、複数の段落を持つブロック引用符のテキスト配置を簡単に切り替えることができます。ここで実際の動作を確認してください。
:empty
何も含まないスタイリング要素を要求する疑似クラスがすでにあります。空の状態をターゲットにする限り、期待どおりに機能しません。要素を空でないものとして認識するには、内部に1つのスペースで十分です。
この場合に使用するのは理想的ではありません:empty
。コンテンツのないカードもいくつか含まれるカードグリッドを作成しましょう。:has()
空のカードの状態をセレクターでスタイリングします。
記事のスタイルを設定する際、タイプ要素とブロック要素を揃えておくのは難しい作業です。コードブロック、図、およびブロック引用符を一般的な型要素と混合する例を考えてみましょう。
ブロック要素は、さまざまな活版印刷エンティティの中で目立つように、より垂直方向の間隔と装飾を持たせる必要があります。これを処理するためのCSSがいくつかあります。
p {
margin: 0;
}
p:not(:last-child) {
margin-bottom: 1.5em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.3;
margin: 1.5em 0 1.5rem;
color: #111;
}
pre,
figure,
blockquote {
margin: 3em 0;
}
figcaption {
margin-top: 1em;
font-size: 0.75em;
color: #888;
text-align: center;
}
上記のスニペットは、ここに示すように、見出しとブロック要素の間に不均一な垂直方向の間隔を生成します。しかし、以前の兄弟選択ハックを使用して、これらの不規則性を補うことは可能です。
CSSでCTAまたはボタンコンポーネントを2つのバリエーションで作成するとします。最初のコンポーネントはデフォルトのプレーンボタンで、2番目のコンポーネントはアイコン付きです。
:has()
これで、そのために2つの別々のクラスを作成することを計画している場合は、セレクターを使用して簡単に回避できます。キャッチは、単に子の.btn
要素をチェックし、.btn-icon
それに応じてスタイルを設定することです。
もちろん、ヘッダーコンポーネントに2つのレイアウトバリエーションがあるとします。1つは固定幅で、もう1つは液体です。
ヘッダーのコンテンツを固定幅内に維持するには、ヘッダー内にコンテンツラッパー要素を追加する必要があります。これら2つのヘッダーバージョンのマークアップの唯一の違いは、ラッパー要素です。
次に、以下のデモンストレーションに示すように、:has()
とセレクターをペアにして、CSSクラスを追加できます。:not()
レイアウトを調整する別の例は、グリッド内の列の数が特定の数に達したらすぐに変更することです。
minmax()
これは、列をグリッドに合わせるのに最適な幅を決定する関数を使用していない場合に便利です。
上記のように、グリッドは2つのアイテムのマークを超えるとすぐに、自動的に3列に調整されます。
対話性は、フィードバックに適切に接続されている場合に最もよく定義されます。インタラクティブなHTMLフォームに関しては、入力に関するフィードバックをユーザーに提供することが最善の方法です。
:has()
、、:valid
および疑似クラスの助けを借りて、:invalid
JavaScriptを使用せずに、フォームをより動的にすることができます。
上記の例は、:has()
セレクターのサポートが見つからない場合のエラーダイアログを示しています。これは@supports
、以下のコードスニペットに示すように、CSSルールを使用して実行できます。
@supports (selector(:has(*))) {
.selector:has(...) {
...
}
}
上記は、サポートを確認し、必要に応じて要素のスタイルを設定するための段階的な方法です。コードベースがいくつかの新機能を直接使用する場合、同じものの下位互換性のあるバージョンを作成する方法は次のとおりです。
@supports not (selector(:has(*))) {
.selector {
...
}
}
同じことを使用して、サポートが見つからなかった場合にユーザーにプロンプトを表示することもできます。
JavaScriptのSupportAPIを使用して、さまざまな機能のブラウザーサポートを検出することもできます。:has()
純粋にJavaScriptでサポートをチェックする例を次に示します。
if(!CSS.supports('selector(html:has(body))'))) { // if not supported
// Use the conventional JavaScript ways to emulate :has()
}
:has()
上記の記事では、レベル4のCSSセレクターについて学びました。そのニーズ、フロントエンドプロジェクトでJavaScriptを置き換えることができるいくつかのケース、および一般的なユースケースから高度なユースケースまでカバーしました。
また、さまざまなブラウザーによって提供されている現在のサポートについて説明し、ブラウザーのサポートを確認する方法を学びました。
ずっと読んでくれてありがとう。これを通して何か新しいことを学んだことを願っています。:has()
コメントでどのように役立つ かについて、より多くの例を自由に共有してください。
ソース:https ://blog.logrocket.com/advanced-guide-css-has-selector/
1659146400
CSS:has()
疑似クラスは、何年もの間最も待望されていた機能の1つです。これはレベル4のCSSセレクターであり、 Chrome 105以降で完全にサポートされる機能として利用できるようになり、他のブラウザーでもまもなく通常の機能になる可能性があります。
in CSSはリレーショナル疑似クラスであり、:has()
特定の要素に特定の子要素が含まれているかどうかを確認し、一致する要素が見つかった場合はそれを選択して、それに応じてスタイルを設定できます。
この記事では、:has()
セレクターの必要性、その一般的な使用法、単純なものから高度なものまでのさまざまなアプリケーションとユースケース、ブラウザーの互換性、およびフォールバックについて説明します。
:has()
セレクターが必要なのですか?ほとんどの開発者は、CSSがデフォルトでサポートしていない特定の機能をJavaScriptに依存しています。ただし、今日のWebブラウザーはこれまでになく強力であり、多くの新しく興味深いCSS機能への扉を開いています。
:has()
セレクターはそのような機能の1つです。子ではなく親で機能し、セレクターのコンマ区切りリストを引数として使用して、それが表す要素の子の間で一致するものを探します。その機能はjQueryhas()
メソッドに似ています。
:has()
フロントエンド開発におけるセレクターの一般的なニーズのいくつかを調べて、この機能が何年にもわたって非常に高い需要があった理由を説明しましょう。
1つは、要素に他の特定の要素が含まれているかどうかを確認し、それに応じてスタイルを設定する可能性です。あなたがここで見ることができるように、JavaScriptは以前これをする唯一の方法でした:
let content = document.querySelector("#content"),
headings = []
if(content) {
headings = content.querySelectorAll("h1, h2, h3")
}
if(headings.length) {
// do something
}
上記のコードquerySelectorAll
では、見出しの分割要素をチェックするためのWebAPIメソッドであるを使用しました。このメソッドは、指定された要素のNodeListを返します。
空のNodeListは、直接の親に要素が存在しないことを意味します。上記の実装はここにあります。または、 CSSの:has()
代替案をここで確認できます。
2つ目は、子から親要素を選択する機能です。繰り返しになりますが、そうするためのCSS機能がないため、開発者はWebAPIのparentNodeプロパティに依存しています。
let el = document.querySelector(".someElement"),
elParent = null
if(el) {
elParent = el.parentNode
}
上記のコードのCodePenデモと、セレクターがこれを実装する方法:has()
をここで表示し ます。
最後に、特定の要素の前の兄弟を選択する機能があります。CSSの兄弟セレクターを使用すると、次の兄弟を選択できますが、前の兄弟を選択するCSSのみの方法はありませんでした。JavaScriptの実装は次のようになります(CodePenのデモはこちらからご覧ください)。
let el = document.querySelector(".someElement"),
elPs = null
if(el) {
elPs = el.previousElementSibling
}
セレクターを使用してこのアクションを実行する方法については、:has()
こちらをご覧ください。
上記でJavaScriptを使用して行ったすべてのことは、CSSを使用して実現できるようになりました:has()
。Google Chromeでこの機能を有効にしてテストする方法を学習した後、次のセクションでそれらを1つずつ説明します。
:has()
古いバージョンのChrome(v.101-104)を使用している場合は、Chromeフラグからこの機能を有効にできます。Chrome 101以降を使用していることを確認し、ブラウザのアドレスバーからchrome://flagsに移動します。
Experimental Web Platformの機能を[有効]に設定すると、準備が整います。:has()
ブラウザを再起動すると、ChromeブラウザでCSSを操作できます。
:has()
セレクターは何をしますか?:has()
疑似クラス、その使用法、およびプロパティを調べてみましょう。疑似クラスであるため、コロンを使用して任意のセレクターにアタッチでき、パラメーターとしてクラス、ID、およびHTMLタグを受け入れます。
以下のコードは、その一般的な使用法と構文を説明しています。クラスは、疑似クラス.selector
を使用してパラメーターとして渡された要素が含まれている場合にのみ選択されます。has()
.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
:has()
適切と思われる場合はいつでも、複数の疑似クラスを次々にチェーンできます。以下のコードは、この連鎖がどのように機能するかを示しています。
.selector:has(div):has(.class):has(#id) {
...
}
チェーンと同様に、複数の要素セレクターのリストを提供することもできますが、はるかに効率的です。
.selector:has(div, .class, #id) {
...
}
誤って無効な要素セレクターを:has()
疑似クラスに指定したとします。それを無視して、有効なセレクターのみを検討するのは十分にインテリジェントです。
.selector:has(div, accordion, .class, ::lobster, #id) {
...
}
accordion
および::lobster
は無効なセレクターであり、上記の場合は無視されます。開発者ツールにCSSエラーやアラートは表示されません。
:has()
CSSのセレクターが役立つシナリオの例をいくつか見てみましょう。
:has()
セレクターのデフォルトの動作は、特定の要素のセットが含まれている場合に何かを選択することであるため、これはセレクターの最も一般的な使用法である可能性があります。しかし、子要素のみを認識している場合はどうなるでしょうか。
ここでは、ユニバーサルセレクター(*
):has()
と子コンビネーター(>
)を使用して、親について何も知らなくてもすばやく親を選択できます。
上記のプロパティセグメントで説明したように、:has()
複数のエンティティのリストを渡すことができます。つまり、特定の要素内で必要な数のセレクターを確認できます。
:has()
前の兄弟の選択は、CSS隣接兄弟コンビネータを疑似クラスと組み合わせることによって可能になります。
ご存知かもしれませんが、隣接する兄弟コンビネータは、特定の要素の次の兄弟を選択します。この動作をで使用しhas()
て、前の兄弟を取得できます。簡単に言えば、要素に次の兄弟がある場合、コンビネータを使用して簡単に選択でき:has()
ます+
。
:has()
セレクターを使用すると、特定の子要素がある場合とない場合のスタイリングを回避できます。キャプションのある場合とない場合のFigure要素は、ここでの完璧な例です。
figcaption
要素はあるがテキストが含まれていない場合はどうなりますか?その場合、:not
と:empty
セレクターを使用してコンテンツをチェックできます。
図の装飾と同様に、複数の段落を持つブロック引用符のテキスト配置を簡単に切り替えることができます。ここで実際の動作を確認してください。
:empty
何も含まないスタイリング要素を要求する疑似クラスがすでにあります。空の状態をターゲットにする限り、期待どおりに機能しません。要素を空でないものとして認識するには、内部に1つのスペースで十分です。
この場合に使用するのは理想的ではありません:empty
。コンテンツのないカードもいくつか含まれるカードグリッドを作成しましょう。:has()
空のカードの状態をセレクターでスタイリングします。
記事のスタイルを設定する際、タイプ要素とブロック要素を揃えておくのは難しい作業です。コードブロック、図、およびブロック引用符を一般的な型要素と混合する例を考えてみましょう。
ブロック要素は、さまざまな活版印刷エンティティの中で目立つように、より垂直方向の間隔と装飾を持たせる必要があります。これを処理するためのCSSがいくつかあります。
p {
margin: 0;
}
p:not(:last-child) {
margin-bottom: 1.5em;
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.3;
margin: 1.5em 0 1.5rem;
color: #111;
}
pre,
figure,
blockquote {
margin: 3em 0;
}
figcaption {
margin-top: 1em;
font-size: 0.75em;
color: #888;
text-align: center;
}
上記のスニペットは、ここに示すように、見出しとブロック要素の間に不均一な垂直方向の間隔を生成します。しかし、以前の兄弟選択ハックを使用して、これらの不規則性を補うことは可能です。
CSSでCTAまたはボタンコンポーネントを2つのバリエーションで作成するとします。最初のコンポーネントはデフォルトのプレーンボタンで、2番目のコンポーネントはアイコン付きです。
:has()
これで、そのために2つの別々のクラスを作成することを計画している場合は、セレクターを使用して簡単に回避できます。キャッチは、単に子の.btn
要素をチェックし、.btn-icon
それに応じてスタイルを設定することです。
もちろん、ヘッダーコンポーネントに2つのレイアウトバリエーションがあるとします。1つは固定幅で、もう1つは液体です。
ヘッダーのコンテンツを固定幅内に維持するには、ヘッダー内にコンテンツラッパー要素を追加する必要があります。これら2つのヘッダーバージョンのマークアップの唯一の違いは、ラッパー要素です。
次に、以下のデモンストレーションに示すように、:has()
とセレクターをペアにして、CSSクラスを追加できます。:not()
レイアウトを調整する別の例は、グリッド内の列の数が特定の数に達したらすぐに変更することです。
minmax()
これは、列をグリッドに合わせるのに最適な幅を決定する関数を使用していない場合に便利です。
上記のように、グリッドは2つのアイテムのマークを超えるとすぐに、自動的に3列に調整されます。
対話性は、フィードバックに適切に接続されている場合に最もよく定義されます。インタラクティブなHTMLフォームに関しては、入力に関するフィードバックをユーザーに提供することが最善の方法です。
:has()
、、:valid
および疑似クラスの助けを借りて、:invalid
JavaScriptを使用せずに、フォームをより動的にすることができます。
上記の例は、:has()
セレクターのサポートが見つからない場合のエラーダイアログを示しています。これは@supports
、以下のコードスニペットに示すように、CSSルールを使用して実行できます。
@supports (selector(:has(*))) {
.selector:has(...) {
...
}
}
上記は、サポートを確認し、必要に応じて要素のスタイルを設定するための段階的な方法です。コードベースがいくつかの新機能を直接使用する場合、同じものの下位互換性のあるバージョンを作成する方法は次のとおりです。
@supports not (selector(:has(*))) {
.selector {
...
}
}
同じことを使用して、サポートが見つからなかった場合にユーザーにプロンプトを表示することもできます。
JavaScriptのSupportAPIを使用して、さまざまな機能のブラウザーサポートを検出することもできます。:has()
純粋にJavaScriptでサポートをチェックする例を次に示します。
if(!CSS.supports('selector(html:has(body))'))) { // if not supported
// Use the conventional JavaScript ways to emulate :has()
}
:has()
上記の記事では、レベル4のCSSセレクターについて学びました。そのニーズ、フロントエンドプロジェクトでJavaScriptを置き換えることができるいくつかのケース、および一般的なユースケースから高度なユースケースまでカバーしました。
また、さまざまなブラウザーによって提供されている現在のサポートについて説明し、ブラウザーのサポートを確認する方法を学びました。
ずっと読んでくれてありがとう。これを通して何か新しいことを学んだことを願っています。:has()
コメントでどのように役立つ かについて、より多くの例を自由に共有してください。
ソース:https ://blog.logrocket.com/advanced-guide-css-has-selector/