これは、作者がどのように:first-child
機能するかを誤解している著者の最も有名な例の1つです。CSS2で導入された:first-child
疑似クラスは、その親の最初の子を表します。それでおしまい。複合セレクターの残りの部分で指定された条件に最初に一致する子要素を選択するという非常に一般的な誤解があります。セレクターの動作方法(説明についてはこちらを参照)が原因で、それは単に正しくありません。
セレクターレベル3では、:first-of-type
要素タイプの兄弟間の最初の要素を表す疑似クラスが導入されています。この回答は、との違いをイラストで説明:first-child
してい:first-of-type
ます。ただし、と同様に:first-child
、他の条件や属性は調べません。HTMLでは、要素タイプはタグ名で表されます。質問では、そのタイプはp
です。
残念ながら、:first-of-class
特定のクラスの最初の子要素を照合するための同様の疑似クラスはありません。Lea Verouと私が(完全に独立してではありますが)このために思いついた回避策の1つは、まずそのクラスを持つすべての要素に目的のスタイルを適用することです。
/*
* Select all .red children of .home, including the first one,
* and give them a border.
*/
.home > .red {
border: 1px solid red;
}
...次に、オーバーライドルールで一般的な兄弟コンビネータを使用して、最初のクラスの後に来るクラスの要素のスタイルを「取り消し」ます。~
/*
* Select all but the first .red child of .home,
* and remove the border from the previous rule.
*/
.home > .red ~ .red {
border: none;
}
これで、最初の要素のみがclass="red"
境界線を持ちます。
ルールの適用方法を次に示します。
<div class="home">
<span>blah</span> <!-- [1] -->
<p class="red">first</p> <!-- [2] -->
<p class="red">second</p> <!-- [3] -->
<p class="red">third</p> <!-- [3] -->
<p class="red">fourth</p> <!-- [3] -->
</div>
ルールは適用されません。境界線はレンダリングされません。
この要素にはクラスがないred
ため、スキップされます。
最初のルールのみが適用されます。赤い枠が表示されます。
この要素にはclassがred
ありますがred
、親のクラスを持つ要素が前にありません。したがって、2番目の規則は適用されず、最初の規則のみが適用され、要素はその境界を維持します。
両方のルールが適用されます。境界線はレンダリングされません。
この要素にはクラスがありred
ます。また、クラスの前に少なくとも1つの他の要素がありred
ます。したがって、両方のルールが適用され、2番目のborder
宣言が最初の宣言をオーバーライドし、いわばそれを「取り消す」ことになります。
それはセレクタ3で導入されましたが、とは違ってボーナスとして、一般的な兄弟コンビネータは、実際にはかなりIE7でうまくサポートされており、新しいもの:first-of-type
と:nth-of-type()
のみ以降IE9でサポートされています。優れたブラウザサポートが必要な場合は、幸運です。
実際、兄弟コンビネーターがこの手法の唯一の重要なコンポーネントであり、そのような素晴らしいブラウザーサポートを備えているという事実により、この手法は非常に用途が広くなり、クラスセレクター以外の要素によるフィルタリングにも適用できます。
これを使用して:first-of-type
、クラスセレクターの代わりにタイプセレクターを提供するだけで、IE7およびIE8で回避できます(この場合も、後のセクションで、誤った使用法について詳しく説明します)。
article > p {
/* Apply styles to article > p:first-of-type, which may or may not be :first-child */
}
article > p ~ p {
/* Undo the above styles for every subsequent article > p */
}
クラスの代わりに、属性セレクターまたはその他の単純なセレクターでフィルタリングできます。
このオーバーライド手法を疑似要素と組み合わせることもできます疑似要素は技術的には単純なセレクターではありませんが。
これが機能するためには、最初のルールを上書きできるように、他の兄弟要素のデフォルトスタイルを事前に知っておく必要があることに注意してください。さらに、これにはCSSのルールのオーバーライドが含まれるため、セレクターAPIで使用する単一のセレクターで同じことを達成することはできませんまたはSeleniumのCSSロケーター。
Selectors 4 が:nth-child()
表記に拡張機能(元々はと呼ばれる完全に新しい疑似クラス:nth-match()
)を導入していることは言及に値します。これ:nth-child(1 of .red)
により、架空ののようなものを使用できます.red:first-of-class
。比較的最近の提案であるため、相互運用可能な実装がまだなく、本番サイトで使用することはできません。うまくいけば、これはすぐに変わるでしょう。それまでの間、私が提案した回避策はほとんどの場合に機能するはずです。
この回答は、質問が特定のクラスを持つすべての最初の子要素を探すことを前提としていることに注意してください。ドキュメント全体にわたる複雑なセレクターのn番目の一致には、疑似クラスも汎用のCSSソリューションもありません。ソリューションが存在するかどうかは、ドキュメントの構造に大きく依存します。jQueryが提供し:eq()
、:first
、:last
およびよりこの目的のために、しかし、それを再び注意して、彼らは非常に異なるから関数:nth-child()
ら。Selectors APIを使用するdocument.querySelector()
と、最初の一致を取得するために使用できます。
var first = document.querySelector('.home > .red');
またはdocument.querySelectorAll()
、特定の一致を選択するためにインデクサーと一緒に使用します。
var redElements = document.querySelectorAll('.home > .red');
var first = redElements[0];
var second = redElements[1];
// etc
フィリップドーブマイヤー.red:nth-of-type(1)
によって最初に受け入れられた回答の解決策は機能しますが(元はマーティンによって作成されたが、その後削除されました)、期待どおりの動作をしません。
たとえばp
、元のマークアップでのみを選択したい場合:
<p class="red"></p>
<div class="red"></div>
...次に使用することはできません.red:first-of-type
(と同等.red:nth-of-type(1)
)。各要素はその型の最初(かつ唯一)であり(p
そしてdiv
それぞれ)、セレクターによって両方が一致します。
特定のクラスの最初の要素がそのタイプの最初の要素でもある場合、疑似クラスは機能しますが、これは偶然にのみ発生します。この振る舞いはフィリップの答えに示されています。この要素の前に同じタイプの要素を挿入すると、セレクターは失敗します。更新されたマークアップを取る:
<div class="home">
<span>blah</span>
<p class="red">first</p>
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
</div>
でのルールの適用.red:first-of-type
は機能しますがp
、クラスなしで別のルールを追加すると、次のようになります。
<div class="home">
<span>blah</span>
<p>dummy</p>
<p class="red">first</p>
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
</div>
...最初の.red
要素が2番目の p
要素になるため、セレクターはすぐに失敗します。