Konstantin Konstantin - 4 months ago 13
CSS Question

css3 selectors and pseudo-classes

Please explain why in some cases pseudo-classes in conjunction with CSS-selectors work and sometimes not.

The Code (https://jsfiddle.net/aspanoz/m1sg4496/):




div.wrapper {
margin-bottom: 10px
}
div[class*="myclass"]:not(:first-of-type) {
color: green
}
div[class*="myclass"]:first-of-type {
color: red
}

<div class="wrapper">
<div class="myclass">This text should appear red.</div>
<div class="myclass">This text should appear green.</div>
<div class="myclass">This text should appear green.</div>
<div>this :first-of-type working as exepted</div>
</div>
<div class="wrapper">
<div>but this :first-of-type fail</div>
<div class="myclass">This text should appear red.</div>
<div class="myclass">This text should appear green.</div>
<div class="myclass">This text should appear green.</div>
</div>




Answer

The word "type" in the name of the first-of-type pseudo-class refers to the tag type (i.e. tag name), not the selector that precedes it.

The official definition (from Selectors Level 3) is:

Same as :nth-of-type(1). The :first-of-type pseudo-class represents an element that is the first sibling of its type in the list of children of its parent element.

Here is the selector you've chosen.

div[class*="myclass"]:first-of-type

This code selects elements that meet both of the following conditions.

  1. The class attribute must contain "myclass", and
  2. It must be the first div element within its container.

In your second example, this selector results in fail-to-find because there are not elements which match both conditions.

There exists a bit of a CSS hack which can select only the first element that matches your selector. My code here is based on this very thorough answer. It depends on the general sibling selector and the nature of CSS specificity.

div.wrapper {
  margin-bottom: 10px
}

/* first select all of your items */
div[class*="myclass"] {
  /* apply the "special" styling here */
  color: red;
}

/* use general sibling selector to grab all except the first */
div[class*="myclass"] ~ div[class*="myclass"] {
  /* "undo" your style on these */
  color: green;
}
<div class="wrapper">
  <div>This text is unaffected.</div>
  <div class="myclass">This text should appear red.</div>
  <div class="myclass">This text should appear green.</div>
  <div class="myclass">This text should appear green.</div>
</div>

<div class="wrapper">
  <div class="myclass">This text should appear red.</div>
  <div class="myclass">This text should appear green.</div>
  <div class="myclass">This text should appear green.</div>
  <div>This text is unaffected.</div>
</div>

<div class="wrapper">
  <div class="myclass">This text should appear red.</div>
  <div class="myclass">This text should appear green.</div>
  <div>This text is unaffected.</div>
  <div class="myclass">This text should appear green.</div>
</div>