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

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

.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的第一个孩子?

1465580 次浏览

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

firstthird将是红色的。

对于您的情况,您可以使用: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或更早版本)。

要匹配您的选择器,元素的类名必须为red,并且必须是其父元素的第一个子元素。

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

由于其他答案涵盖了它的错误,我会尝试另一半,如何修复它。不幸的是,我不知道你在这里有仅CSS的解决方案,至少不是我能想到的。不过,还有一些其他的选择……

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

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

    css:

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

    此CSS仅匹配具有两者firstred类的元素。

  2. 或者,在JavaScript中执行相同的操作,例如,这是您将使用的jQuery来执行此操作,使用与上述相同的CSS:

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

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

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

不幸的是,没有类似的:first-of-class伪类来匹配给定类的第一个子元素。当这个答案第一次发布的时候,新发布的选择器级别4的FPWD引入了#1伪类,围绕现有的选择器机制设计,正如我在第一段中提到的,通过添加一个选择器列表参数,你可以通过它提供复合选择器的其余部分来获得所需的过滤行为。近年来,这个功能是归入#2本身,选择器列表作为可选的第二个参数出现,以简化事情并避免:nth-match()在整个文档中匹配的错误印象(参见下面的最后注释)。

当我们等待跨浏览器支持的时候(说真的,已经快10年了,在过去的5年里只有一个实现),leaverou和我独立开发的一个解决方法(她先做的!)是首先将您想要的样式应用于该类的所有元素:

/** Select all .red children of .home, including the first one,* and give them a border.*/.home > .red {border: 1px solid red;}

…然后“撤消”具有在第一个之后类的元素的样式,在覆盖规则中使用一般同胞组合子#0

/** 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 {border: 1px solid red;}
.home > .red ~ .red {border: none;}
<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. 不应用规则;不呈现边框。
    这个元素没有类red,所以它被跳过了。

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

  3. 应用这两个规则;不呈现边框。
    此元素具有类red。它之前还有至少一个具有类red的其他元素。因此应用了两个规则,第二个border声明覆盖了第一个,从而“撤消”了它,可以这么说。

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

事实上,兄弟组合器是该技术中唯一重要的组件,它具有如此惊人的浏览器支持,这使得该技术非常通用-除了类选择器之外,您还可以通过其他方式调整它以过滤元素:

  • 您可以使用它来解决IE7和IE8中的:first-of-type,只需提供类型选择器而不是类选择器(在后面的问题中,更多关于它的错误用法):

     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中的覆盖规则,因此您无法使用单个选择器来实现与选择器APISelenium的CSS定位器相同的功能。

最后,请记住,这个答案假设问题正在寻找具有给定类的任何数量的第一个子元素。对于复杂选择器在整个文档的第n个匹配,既没有伪类,也没有通用的CSS解决方案-解决方案是否存在在很大程度上取决于文档结构。jQuery为此提供了:eq():first:last等,但再次注意它们的功能与#3 et al非常不同。使用选择器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

尽管Martyn717515">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),所以两者将由选择器匹配。

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

<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元素。

正确答案是:

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

第一部分:如果元素是它的父元素的第一个并且具有类“red”,它将获得边界。
第二部分:如果“. red”元素不是它的父元素的第一个,而是紧跟在没有类“. red”的元素之后,它也应该得到上述边界的荣誉。

摆弄或它没有发生。

Philip Daubmeier的回答,虽然被接受,是不正确的-见所附小提琴。Bolt时钟的答案可以工作,但不必要地定义和覆盖样式
(特别是一个问题,否则它会继承一个不同的边界-你不想声明其他边界:无)

编辑:如果你有“红色”跟在非红色后面好几次,每个“第一个”红色都会得到边框。为了防止这种情况,需要使用螺栓时钟的答案。见小提琴

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

根据你最新的问题

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

这将选择阶级家庭,然后是元素跨度,最后是所有.红色元素,它们紧跟在跨度元素之后。

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

你可以把你的代码改成这样让它工作

<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参考。

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

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

试试这个简单而有效

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

上面的答案太复杂了。

.class:first-of-type { }

这将选择类的第一种类型。MDN源

注意:使用Chrome91和Firefox 89进行测试,2021年6月。

试试这个解决方案:

 .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链接

你可以使用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>

我正在使用下面的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>

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

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>

我相信使用相对选择器+来选择紧随其后的元素,在这里效果最好(之前很少有人建议)。

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

.home p:first-of-type

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

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

你可以试试这样的东西:

.red:first-of-type {border: 5px solid red;}

您也可以将其用于最后一个元素(如果需要):

.red:last-of-type {border: 5px solid red;}

总而言之,在阅读完所有页面和其他页面以及大量留档后。以下是摘要:

  • 对于第一/最后儿童:现在可以安全使用(所有现代浏览器都支持)
  • :第n个孩子()现在也可以安全使用(所有现代浏览器都支持)。但要小心,它甚至计算兄弟姐妹!因此,以下内容无法正常工作:

/* This should select the first 2 element with class display_class* but it will NOT WORK Because the nth-child count even siblings* including the first div skip_class*/.display_class:nth-child(-n+2){background-color:green;}
<ul><li class="skip_class">test 1</li><li class="display_class">test 2 should be in green</li><li class="display_class">test 3 should be in green</li><li class="display_class">test 4</li></ul>

目前,有一个选择器:第n个孩子(-n+2 of. foo)支持按类选择,但现代浏览器不支持,所以没有用。

所以,这给我们留下了Javascript解决方案(我们将修复上面的示例):

// Here we'll go through the elements with the targeted class// and add our classmodifer to only the first 2 elements!

[...document.querySelectorAll('.display_class')].forEach((element,index) => {if (index < 2) element.classList.add('display_class--green');});
.display_class--green {background-color:green;}
<ul><li class="skip_class">test 1</li><li class="display_class">test 2 should be in green</li><li class="display_class">test 3 should be in green</li><li class="display_class">test 4</li></ul>

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

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

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

.red:not(.red ~ .red) {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>

只需使用

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

它将工作。

下面的代码肯定在任何地方都能很好地工作。
它是简单和简短的

<div class="home"><span>blah</span><p class="blue"> first-blue  </p><p class="blue"> second-blue </p><p class="blue"> third-blue  </p>
<p class="red">  first-red   </p><p class="red">  second-red  </p><p class="red">  third-red   </p><p class="red">  fourth-red  </p>
<p class="pink"> first-pink  </p><p class="pink"> second-pink </p>
<p class="red">  new-first-red   </p><p class="red">  new-second-red  </p></div>

我们可以选择first-red

.home .red:not(.home .red ~ .red) {background-color: blue;}

如果你也想选择new-first-red,你应该使用+而不是~

一个快速的'n脏jQuery解决方案,用于在一组具有相同类名的元素中标记第一个和最后一个元素:

$('.my-selector').each(function(index, item) {if (!$(item).next().hasClass('my-selector')) {$(item).addClass('last');}if (!$(item).prev().hasClass('my-selector')) {$(item).addClass('first');}});
.my-selector {padding: 5px;background: #ccc;}
.my-selector.first {background: #fcc;}
.my-selector.last {background: #cfc;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div><span>first element...</span><div class="my-selector">Row 1</div><div class="my-selector">Row 2</div><div class="my-selector">Row 3</div><div class="my-selector">Row 4</div><span>other elements...</span><div class="my-selector">Row 3</div><div class="my-selector">Row 4</div></div>