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

时间:2010-04-26 22:51:13

标签: css css-selectors

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

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

21 个答案:

答案 0 :(得分:1290)

这是作者误解:first-child如何运作的最着名的例子之一。 Introduced in CSS2:first-child伪类代表其父级的第一个孩子。就是这样。这是一个非常普遍的误解,它会选择第一个匹配由复合选择器其余部分指定的条件的子元素。由于选择器的工作方式(请参阅here获得解释),这根本不是真的。

Selectors level 3 introduces a :first-of-type pseudo-class,表示其元素类型的兄弟姐妹中的第一个元素。 This answer通过插图解释了: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;
}

...然后&#34;撤消&#34;具有在第一个之后的类的元素的样式,在最重要的规则中使用the general sibling combinator ~

/* 
 * 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. 未应用任何规则;没有边框呈现。
    此元素没有类red,因此会跳过它。

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

  3. 这两条规则都适用;没有边框呈现。
    该元素具有类red。它前面还有至少一个具有类red的其他元素。因此,两个规则都被应用,第二个border声明覆盖第一个,从而撤消&#34;可以这么说。

  4. 作为奖励,虽然它是在Selectors 3中引入的,但实际上兄弟组合器实际上得到IE7及更新版本的支持,不像:first-of-type:nth-of-type()只有IE9以后才支持。如果您需要良好的浏览器支持,那么您很幸运。

    事实上,兄弟组合器是这项技术中唯一重要的组件,它具有如此惊人的浏览器支持,这使得这种技术非常通用 - 你可以通过它来适应过滤元素其他的东西,除了类选择器:

    • 您可以使用它在IE7和IE8中解决:first-of-type,只需提供一个类型选择器而不是类选择器(再次,在后面的部分中更多地介绍它的错误用法): / p>

      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 */
      }
      
    • 您可以按attribute selectors或任何其他简单选择器而不是类进行过滤。

    • 您也可以将此覆盖技术与pseudo-elements结合使用,即使伪元素在技术上不是简单的选择器。

    请注意,为了使其正常工作,您需要事先知道其他同级元素的默认样式,以便您可以覆盖第一个规则。此外,由于这涉及覆盖CSS中的规则,因此您无法使用单个选择器实现相同的功能,以便与Selectors APISelenium的CSS定位器一起使用。

    值得一提的是,Selectors 4引入了an extension to the :nth-child() notation(最初是一个名为:nth-match()的全新伪类),它允许你使用类似:nth-child(1 of .red)的东西来代替一个假设的.red:first-of-class。作为一个相对较新的提案,还没有足够的可互操作的实现,以便它可以在生产站点中使用。希望这会很快改变。与此同时,我建议的解决方法应该适用于大多数情况。

    请记住,这个答案假定问题是查找具有给定类的每个第一个子元素。对于复杂选择器在整个文档中的第n次匹配,既没有伪类也没有通用的CSS解决方案 - 解决方案是否存在在很大程度上取决于文档结构。为此,jQuery提供了:eq():first:last等等,但请再次注意they function very differently from :nth-child() et al。使用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)),因为每个元素都是其中第一个(也是唯一的)类型(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元素现在是第二个 p元素。

答案 1 :(得分:312)

:first-child选择器与名称一样,用于选择父标记的第一个子标记。孩子必须嵌入在同一个父标签中。您的确切示例将起作用(刚刚尝试过here):

<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将为红色。

<强>更新

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

<html>
<head>
<style type="text/css">
.red:nth-of-type(1)
{
    border:5px solid red;
} 
</style>
</head>

<body>
    <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>
</body>
</html>

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

答案 2 :(得分:67)

正确答案是:

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

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

Fiddle or it didn't happen.

菲利普·道布梅尔的回答虽然被接受了,但却不正确 - 请参阅随附的小提琴 BoltClock的答案可行,但不必要地定义和覆盖样式
(特别是否则会继承不同边框的问题 - 你不想声明其他边框:none)

编辑: 如果你有几次非红色的“红色”,每个“第一”红色将获得边框。为了防止这种情况,人们需要使用BoltClock的答案。见fiddle

答案 3 :(得分: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>

答案 4 :(得分: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>

答案 5 :(得分:8)

由于其他答案涵盖了错误的内容,我将尝试另一半,如何修复它。不幸的是,我不知道你这里有仅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");
    

答案 6 :(得分: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 ,最后选择所有 .red元素,它们紧跟在span元素之后。

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

答案 7 :(得分:5)

我在项目中得到了这个。

&#13;
&#13;
div > .b ~ .b:not(:first-child) {
	background: none;
}
div > .b {
    background: red;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 8 :(得分:3)

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

答案 9 :(得分: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参考资料。

答案 10 :(得分:3)

我在CSS下面使用列表ul li

的背景图片

&#13;
&#13;
#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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 11 :(得分:2)

上述答案过于复杂。

.class:first-of-type { }

这将选择第一类课程。 MDN Source

答案 12 :(得分:2)

试试这个:

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

答案 13 :(得分:1)

尝试这种简单有效的

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

答案 14 :(得分:0)

试试这个解决方案:

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

答案 15 :(得分:0)

只需要第一个,并且只有一个段落变为红色。怎么样?

<!DOCTYPE html><html><head><style>

article p:nth-child(1){background: red}
article p:first-child{background: red}

</style></head><body>

<p style="color:blue">Needed only first and only one paragraph had red. How?</p>

<article>
<p>The first paragraph.</p>
<div><p>The second paragraph.</p></div>
<p>The third paragraph.</p>
<div><p>The fourth paragraph.</p></div>
</article>

</body></html>

答案 16 :(得分:0)

您能尝试这样的事情吗?

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

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

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

答案 17 :(得分:0)

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

  • first / last的孩子:现在可以安全使用(所有现代浏览器都支持)
  • :nth-child()现在也可以安全使用(所有现代浏览器都支持)。 但是要小心,它甚至可以算在内!因此,以下内容将无法正常工作:

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

当前,有一个selector :nth-child(-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>

答案 18 :(得分:-1)

我相信使用相对选择器+来选择紧接着放置的元素,在这里效果最好(之前建议的很少)。

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

.home p:first-of-type

但这是元素选择器而不是第一类。

这里有很好的CSS选择器列表:https://kolosek.com/css-selectors/

答案 19 :(得分:-1)

我刚刚成功使用:first作为CSS选择器。

.red:first

答案 20 :(得分:-5)

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

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