我有一堆元素的类名红色,但我似乎不能选择class="red"使用以下CSS规则的第一个元素:

.home .red:第一个孩子{ 边框:1px纯红色; } < div class = "家" > < span >等等> < /跨度 < p class = "红色" >第一个< / p > < p class = "红色" >第二< / p > < p class = "红色" > < / p >第三 < p class = "红色" >第四< / p > < / div >

这个选择器出了什么问题,我如何纠正它,以类红色为目标的第一个孩子?


当前回答

我很惊讶没有人提到最干净的解决方案:

r:没有。红色~ .红色){ 边框:1px纯红色; } < div class = "家" > < span >等等> < /跨度 < p class = "红色" >第一个< / p > < p class = "红色" >第二< / p > < p class = "红色" > < / p >第三 < p class = "红色" >第四< / p > < / div >

其他回答

这是作者误解第一个孩子如何工作的最著名的例子之一。在CSS2中引入的:first-child伪类表示其父类的第一个子类。就是这样。有一个非常常见的误解,即它会选择第一个匹配复合选择器其余部分指定条件的子元素。由于选择器的工作方式(参见这里的解释),这是不正确的。

选择器级别3引入了一个:类型第一的伪类,它表示其元素类型的兄弟元素中的第一个元素。这个答案用插图解释了:first-child和:first-of-type之间的区别。然而,与:first-child一样,它不查看任何其他条件或属性。在HTML中,元素类型由标记名称表示。题目中,这个类型是p。

Unfortunately, there is no similar :first-of-class pseudo-class for matching the first child element of a given class. At the time this answer was first posted, the newly published FPWD of Selectors level 4 introduced an :nth-match() pseudo-class, designed around existing selector mechanics as I mentioned in the first paragraph by adding a selector-list argument, through which you can supply the rest of the compound selector to get the desired filtering behavior. In recent years this functionality was subsumed into :nth-child() itself, with the selector list appearing as an optional second argument, to simplify things as well as averting the false impression that :nth-match() matched across the entire document (see the final note below).

当我们等待跨浏览器支持的时候(认真地说,已经有将近10年了,在过去的5年里只有一个实现),Lea Verou和我独立开发的一个解决方案(她是第一个做的!)是首先将你想要的样式应用到你所有的类元素上:

/* 
 * 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"的第一个元素有边框。

下面是如何应用这些规则的示例:

.home > .red { 边框:1px纯红色; } .home > .red ~ .red { 边界:没有; } < div class = "家" > < 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 >

No rules are applied; no border is rendered. This element does not have the class red, so it's skipped. Only the first rule is applied; a red border is rendered. This element has the class red, but it's not preceded by any elements with the class red in its parent. Thus the second rule is not applied, only the first, and the element keeps its border. Both rules are applied; no border is rendered. This element has the class red. It is also preceded by at least one other element with the class red. Thus both rules are applied, and the second border declaration overrides the first, thereby "undoing" it, so to speak.

作为奖励,尽管它是在Selectors 3中引入的,但一般的兄弟组合子实际上在IE7和更新版本中得到了很好的支持,而不像:first-of-type和:nth-of-type()只在IE9之后才得到支持。如果您需要良好的浏览器支持,那么您很幸运。

事实上,兄弟组合子是这种技术中唯一重要的组件,而且它有如此惊人的浏览器支持,这使得这种技术非常通用——你可以用它来过滤元素,除了类选择器:

You can use this to work around :first-of-type in IE7 and IE8, by simply supplying a type selector instead of a class selector (again, more on its incorrect usage in the question in a later section): 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 */ } You can filter by attribute selectors or any other simple selectors instead of classes. You can also combine this overriding technique with pseudo-elements even though pseudo-elements technically aren't simple selectors.

请注意,为了使其工作,您需要提前知道其他兄弟元素的默认样式是什么,以便可以覆盖第一个规则。此外,由于这涉及到CSS中的覆盖规则,您无法通过使用Selectors API或Selenium的CSS定位器来实现相同的功能。

On a final note, keep in mind that this answer assumes that the question is looking for any number of first child elements having a given class. There is neither a pseudo-class nor even a generic CSS solution for the nth match of a complex selector across the entire document — whether a solution exists depends heavily on the document structure. jQuery provides :eq(), :first, :last and more for this purpose, but note again that they function very differently from :nth-child() et al. Using the Selectors API, you can either use document.querySelector() to obtain the very first match:

var first = document.querySelector('.home > .red');

或者使用document.querySelectorAll()与索引器一起选择任何特定的匹配:

var redElements = document.querySelectorAll('.home > .red');
var first = redElements[0];
var second = redElements[1];
// etc

虽然Philip Daubmeier最初接受的答案中的。red:n -of-type(1)解决方案有效(最初由Martyn编写,但后来被删除了),但它并没有像您期望的那样表现。

例如,如果你只想选择这里的p:

<p class="red"></p>
<div class="red"></div>

... 那么你就不能使用.red:first-of-type(相当于.red:nth-of-type(1)),因为每个元素都是它的第一个(也是唯一一个)类型(分别是p和div),所以两者都将被选择器匹配。

当某个类的第一个元素也是其类型的第一个元素时,伪类将工作,但这只是巧合。这种行为在Philip的回答中得到了证明。当您在该元素之前插入一个相同类型的元素时,选择器将失败。从问题中获取标记:

<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元素现在是第二个p元素。

我相信使用相对选择器+来选择紧随其后的元素,在这里工作得最好(正如之前很少有人建议的那样)。

这种情况下也可以使用这个选择器

.home p:first-of-type

但这是元素选择器,不是类选择器。

这里你有一个CSS选择器列表:https://kolosek.com/css-selectors/

试试这个解决方案:

.home p:first-of-type { 边框:5px纯红色; 宽度:100%; 显示:块; } < div class = "家" > < span >等等> < /跨度 < p class = "红色" >第一个< / p > < p class = "红色" >第二< / p > < p class = "红色" > < / p >第三 < p class = "红色" >第四< / p > < / div >

CodePen链接

由于其他答案涵盖了它的问题,我将尝试另一半,如何解决它。不幸的是,我不知道你有一个CSS唯一的解决方案,至少不是我能想到的。还有一些其他的选择....

在生成元素时给元素赋一个first类,如下所示: <p class="red first"></p> . < div class = "红色" > < / div > CSS: 当代。红色{ 边框:5px纯红色; } 这个CSS只匹配第一个类和红色类的元素。 或者,在JavaScript中做同样的事情,例如这里是你会使用jQuery来做这件事,使用与上面相同的CSS: $ (r:首先).addClass(“第一”);

我想很多人已经解释过了。您的代码只选择了第一个实例的第一个子对象。如果你想选择红色类的所有第一个子类,你需要使用

.home > .red:first-child {
    /* put your styling here */
}