类的第一个元素的CSS选择器


944

我有一堆带有类名的元素red,但是我似乎无法class="red"使用以下CSS规则选择第一个元素:

.red:first-child {
    border: 5px solid red;
}
<p class="red"></p>
<div class="red"></div>

该选择器有什么问题,我该如何纠正?

多亏了这些评论,我才知道该元素必须是其父元素的第一个子元素才能被选中,而我并非如此。我具有以下结构,并且该规则失败,如注释中所述:

.home .red:first-child {
    border: 1px solid red;
}
<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


对于那些由于我的示例(p,div)中的元素类型不同而感到困惑的人,使它们相同也行不通,问题仍然存在。
Rajat 2010年

4
我认为这是:first-child选择器应该起作用的方式……
Felix Eve

28
:first-child可能不是一个很好的名字。如果您有一个儿子,然后是一个女儿,您不会称您的女儿为长子。同样,第一个.home> .red不是.home的第一个子级,因此这样称呼它是不合适的。
BoltClock

不,这是:first-of-type应该是如何工作的
Evan Thompson

@EvanThompson那怎么:first-of-type 工作。
TylerH

Answers:


1422

这是作者误解:first-child工作方式的最著名例子之一。在CSS2介绍,该:first-child伪类表示其父的第一个孩子。而已。有一个非常普遍的误解,认为它选择第一个与其余复合选择器指定的条件相匹配的子元素。由于选择器的工作方式(请参阅此处以获取解释),这根本不是事实。

选择器级别3引入了一个:first-of-type伪类,该伪类表示其元素类型的同级元素中的第一个元素。该答案通过插图说明了:first-child和之间的区别:first-of-type。但是,与一样:first-child,它不会查看任何其他条件或属性。在HTML中,元素类型由标记名称表示。在问题中,该类型为p

不幸的是,没有类似的:first-of-class伪类可以匹配给定类的第一个子元素。我和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"边框。

这是如何应用规则的说明:

<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>
  1. 没有规则适用;没有边框。
    该元素没有class red,因此被跳过。

  2. 仅应用第一个规则;呈现红色边框。
    该元素具有class red,但是它的red父元素中没有带有该类的任何元素。因此,不应用第二条规则,仅应用第一条规则,并且元素保留其边界。

  3. 这两个规则都适用;没有边框。
    该元素具有类red。在类的前面还至少有一个其他元素red。因此,这两个规则都适用,第二个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中的重写规则,因此,使用一个与Selectors APISelenium的CSS定位器一起使用的选择器无法实现同一目的。

值得一提的是,选择器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

尽管Philip Daubmeier.red:nth-of-type(1)最初接受的答案中的解决方案有效(该解决方案最初是由Martyn撰写,但此后删除了),但它的行为方式并不符合您的期望。

例如,如果您只想p在原始标记中选择:

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

...那么您将无法使用.red:first-of-type(等效于.red:nth-of-type(1)),因为每个元素都是其类型(pdiv)中的第一个(也是唯一),因此选择器将同时匹配这两个元素。

当某个类的第一个元素也是其类型的第一个元素时,伪类将起作用,但这仅是巧合。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元素。


15
那么,有什么方法可以模仿:last-of-class吗?选择类的最后一个元素。
火箭危险品

1
@Rocket:不是,我可以看到:(
BoltClock

4
同胞的好技术。可能值得注意的是,它也可以与多个同级组合器一起工作,例如p〜p〜p
Legolas

2
@BoltClock是的,很抱歉,我是来这里寻求解决方案的,我不太关心OP的特定情况。我实际上不明白为什么这样的general sibling selector ~工作就像:not(:first-of-*)针对特定类型的a 一样,我假设它应该将规则应用于每个匹配元素,但是即使有3个或更多可能的匹配,它也仅适用于第一个匹配。
Gerard Reches

2
根据caniuse的说法,该:nth-child(1 of .foo)扩展已在Safari 9.1+上实现。(我尚未检查)
Danield

329

:first-child选择的目的是,像它的名字说,选择父标签的第一个孩子。子项必须嵌入相同的父标记中。您的确切示例将起作用(只需在此处进行尝试):

<body>
    <p class="red">first</p>
    <div class="red">second</div>
</body>

也许您已将标签嵌套在其他父标签中?您的课程标签red真的是父母标签下的第一个标签吗?

还要注意,这不仅适用于整个文档中的第一个这样的标签,而且每次在其周围包裹新的父对象时,例如:

<div>
    <p class="red">first</p>
    <div class="red">second</div>
</div>
<div>
    <p class="red">third</p>
    <div class="red">fourth</div>
</div>

first然后third会变成红色。

更新:

我不知道为什么martyn删除了他的答案,但是他有解决方案,:nth-of-type选择器:

.red:nth-of-type(1)
{
    border:5px solid red;
} 
<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>

归功于Martyn。更多信息在这里。请注意,这是一个CSS 3选择器,因此并非所有浏览器都能识别它(例如IE8或更早的版本)。


可能是我的错-正如我向Martyn指出的那样,像CSS3选择器这样:nth-of-type的小问题是,它在任何当前版本的IE中都无法正常工作。
三月Örlygsson

25
我读这个有点困惑。严格.red:nth-of-type(1)选择任何元素,其中(a)是其元素类型的第一个子元素,并且(b)具有“ red”类。因此,在示例中,如果第一个<p>没有类“ red”,则不会选择它。或者,如果<span>和第一个<p>都具有“红色”类,则将它们都选中。 jsfiddle.net/fvAxn
大卫

7
@Dan Mundy::first-of-type等同于:nth-of-type(1),所以当然也可以。由于我的回答中所述的相同原因,它也可能以相同的方式失败。
BoltClock

4
@David我肯定:nth-of-type在说“类型”时表示“元素/标签”。因此,它仅考虑元素,而不考虑类之类的东西。
gcampbell

2
@gcampbell:是的,这就是它的意思,这就是为什么这个答案有缺陷的原因。选择“类型”一词的原因是为了避免将选择器与HTML / XML耦合,因为并非所有语言都具有定义元素的“标签”概念。
BoltClock

74

正确答案是:

.red:first-child, :not(.red) + .red { border:5px solid red }

第一部分:如果元素是其父元素的第一个元素,并且具有“ red”类,则它将获得边框。
第二部分:如果“ .red”元素不是其父元素的第一个元素,而是紧随其后的是不具有“ .red”类的元素,则也应享有该边界的荣誉。

提琴或没有发生。

菲利普·道布迈尔的答案虽然被接受,但却是不正确的-参见附件。
BoltClock的答案会起作用,但是不必要地定义和覆盖样式
(尤其是这样的问题,否则它将继承不同的边框-您不想将其他声明为border:none)

编辑:如果您多次跟随非红色“红色”,则每个“第一个”红色将获得边框。为避免这种情况,需要使用BoltClock的答案。见小提琴


2
这个答案没有错,选择器对于给定的标记正确的,但是我要重申,编辑中提到的情况是为什么我声明至少在不能保证标记结构的情况下有必要进行覆盖的原因,原因仅在于.red跟随a :not(.red)并不总是使其成为.red同级中的第一个。如果需要继承边框,则只需声明即可,border: inherit而不是border: none覆盖规则中。
BoltClock

3
此解决方案是最佳的IMO,因为您可以轻松地为最后一个孩子做同样的事情。
A1rPun 2014年

@ A1rPun您如何更改最后一个孩子的?
威廉

@Willem只需将更first-child改为last-child,但是经过测试,我发现这并不总是有效。
A1rPun 2014年

3
抱歉,它与“具有.red类的第一个子元素”不匹配,而是与“如果具有class .red和非.red元素后具有first .red元素的第一个元素匹配”。这两个不是等效的。小提琴:jsfiddle.net/Vq8PB/166
Gunchars 2015年

19

您可以使用first-of-typenth-of-type(1)

.red {
  color: green;  
}

/* .red:nth-of-type(1) */
.red:first-of-type {
  color: red;  
}
<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>


6
如果您<p></p>span和类别之间的第一个p元素之间有一个,它将无法正常工作red。看看这个JSFiddle
弗朗西斯科·罗梅罗

1
现在,我看到它在他回答的最后一个示例中重现了我在此指出的相同行为。当我尝试您的示例并“玩”一点时,我注意到该行为,并且我想指出,以便将来的读者知道。
弗朗西斯科·罗梅罗

13

上面的答案太复杂了。

.class:first-of-type { }

这将选择第一类。MDN来源


4
我找不到对first-type的任何引用,并且first-of-type仅适用于标签名称;您确定这个答案正确吗?
马特·布罗奇

1
first-type 已重命名为 first-of-type
加百利博览会

7
它不适用于类。这就是它应该工作,因为选择一个类的第n个会比选择一个标签的第n个比较有用。但是':first-of-type'只能由tagName使用。如果恰好碰巧“一流”和“标签第一”指的是同一元素,而他们经常这样做,那么很容易使自己困惑,以为它确实如此工作。然后想知道当您遇到的情况没有解决时,有什么坏处。
埃文·汤普森

2
不知道为什么这不是选定的答案。这完全符合OP的要求,并且运行良好。SMH。
伯内斯托

1
@贝内斯托(Bernesto),当您遇到多个具有相同“类型”元素的情况时,可以说<span>,有几个具有class highlight。该.highlight:first-of-type选择器将选择“类型”与所选择的类,在本例的第一个实例的第一<span>,和不是类的第一个实例highlight。仅当span的第一个实例也具有类突出显示时,才会实现样式。(codepen.io/andrewRmillar/pen/poJKJdJ
Sl4rtib4rtf4st

9

要与选择器匹配,该元素必须具有的类名,red并且必须是其父级的第一个子级。

<div>
    <span class="red"> <!-- MATCH -->
</div>

<div>
    <span>Blah</span>
    <p class="red"> <!-- NO MATCH -->
</div>

<div>
    <span>Blah</span>
    <div><p class="red"></div> <!-- MATCH -->
</div>

这是正确的,这似乎是我的问题,但是有没有办法选择带有类的第一个元素,而不管它是否先于其他元素?
拉贾特

如果您查看了Martyns回答,则不必问这个问题:)
Philip Daubmeier 2010年

9

由于其他答案都涵盖了问题所在,因此我将尝试另一半,以及解决方法。不幸的是,我不知道您在这里只有CSS解决方案,至少我没有想到。不过,还有其他选择。

  1. first生成元素时,为其分配一个类,如下所示:

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

    CSS:

    .first.red {
      border:5px solid red;
    }

    这个CSS只匹配的元素 firstred类。

  2. 另外,也可以在JavaScript中执行相同的操作,例如,这是使用与上述相同的CSS来执行此操作的jQuery:

    $(".red:first").addClass("first");

不久前,我想到了一个仅CSS的解决方案;我在这里将其复制为一个规范的答案。
BoltClock

1
只要没有类似的东西:first-of-class,我还建议您向第一个元素添加一个额外的类。似乎是目前最简单的解决方案。
Kai Noack

7

我在我的项目中得到了这个。

div > .b ~ .b:not(:first-child) {
	background: none;
}
div > .b {
    background: red;
}
<div>
      <p class="a">The first paragraph.</p>
      <p class="a">The second paragraph.</p>
      <p class="b">The third paragraph.</p>
      <p class="b">The fourth paragraph.</p>
  </div>


5

根据您更新的问题

<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>

怎么样

.home span + .red{
      border:1px solid red;
    }

这将选择class home,然后选择span 元素,最后选择在span元素之后立即放置的所有.red元素。

参考:http : //www.w3schools.com/cssref/css_selectors.asp


3

您可以使用nth-of-type(1),但请确保该站点不需要支持IE7等,如果是这种情况,请使用jQuery添加主体类,然后通过IE7主体类查找元素,然后通过元素名称查找,然后添加在第n个孩子的样式中。


3

您可以将代码更改为这样的代码才能正常工作

<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>

这为您完成了工作

.home span + .red{
      border:3px solid green;
    }

这是SnoopCode的CSS参考。


3

我正在使用下面的CSS为列表ul li提供背景图像

#footer .module:nth-of-type(1)>.menu>li:nth-of-type(1){
  background-position: center;
  background-image: url(http://monagentvoyagessuperprix.j3.voyagesendirect.com/images/stories/images_monagentvoyagessuperprix/layout/icon-home.png);
  background-repeat: no-repeat;
}
<footer id="footer">
  <div class="module">
    <ul class="menu ">
      <li class="level1 item308 active current"></li>
      <li> </li>
    </ul> 
  </div>
  <div class="module">
    <ul class="menu "><li></li>
      <li></li> 
    </ul>
  </div>
  <div class="module">
    <ul class="menu ">
      <li></li>
      <li></li>
    </ul>
  </div>
</footer>


2

尝试这个 :

    .class_name > *:first-child {
        border: 1px solid red;
    }

2

由于某种原因,以上答案似乎都没有解决父母的真正第一个也是唯一第一个孩子的情况。

#element_id > .class_name:first-child

如果您只想将此样式仅应用于此代码中的头等子级,则以上所有答案都将失败。

<aside id="element_id">
  Content
  <div class="class_name">First content that need to be styled</div>
  <div class="class_name">
    Second content that don't need to be styled
    <div>
      <div>
        <div class="class_name">deep content - no style</div>
        <div class="class_name">deep content - no style</div>
        <div>
          <div class="class_name">deep content - no style</div>
        </div>
      </div>
    </div>
  </div>
</aside>

1
您的答案基本上已经包含在该问题的前两个最高答案中,没有添加任何内容。而且,您对:first-child伪类的使用会产生误导,因为它在伪类.class_name之前添加不会改变其工作方式,而只是使其充当过滤器。如果您之前有一个div,<div class="class_name">First content that need to be styled</div>则您的选择器将不匹配,因为它不是实际的第一个孩子。
j08691 '16

我认为对于需要信息的人来说不是那么简单。是的,您是对的。这适用于更具体的情况。这就是为什么我认为它可能有用。
Yavor Ivanov

这正是我所需要的,精确而简洁。谢谢@YavorIvanov
–quantum

1

试试这个简单有效的方法

 .home > span + .red{
      border:1px solid red;
    }


-2

试试这个解决方案:

 .home p:first-of-type {
  border:5px solid red;
  width:100%;
  display:block;
}
<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>

CodePen链接


问题是“ 带有类的第一个元素的CSS选择器 ”,而不是“ 带有标签名的第一个元素的CSS选择器 ”。
GeroldBroser恢复莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.