带有类的第一个元素的 CSS 选择器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2717480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CSS selector for first element with class
提问by Rajat
I have a bunch of elements with a class name red
, but I can't seem to select the first element with the class="red"
using the following CSS rule:
我有一堆带有 class name 的元素red
,但我似乎无法class="red"
使用以下 CSS 规则选择第一个元素:
.red:first-child {
border: 5px solid red;
}
<p class="red"></p>
<div class="red"></div>
What is wrong in this selector and how do I correct it?
这个选择器有什么问题,我该如何纠正?
Thanks to the comments, I figured out that the element has to be the first child of its parent to get selected which is not the case that I have. I have the following structure, and this rule fails as mentioned in the comments:
感谢评论,我发现元素必须是其父元素的第一个子元素才能被选中,而我的情况并非如此。我有以下结构,如评论中所述,此规则失败:
.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>
How can I target the first child with class red
?
我如何针对第一个上课的孩子red
?
回答by BoltClock
This is one of the most well-known examples of authors misunderstanding how :first-child
works. Introduced in CSS2, the :first-child
pseudo-class represents the very first child of its parent. That's it. There's a very common misconception that it picks up whichever child element is the first to match the conditions specified by the rest of the compound selector. Due to the way selectors work (see herefor an explanation), that is simply not true.
这是作者误解:first-child
工作原理的最著名例子之一。CSS2 中引入的:first-child
伪类表示其父类的第一个子类。就是这样。有一个非常普遍的误解,即它选择第一个匹配复合选择器其余部分指定的条件的子元素。由于选择器的工作方式(参见此处的解释),这根本不是真的。
Selectors level 3 introduces a :first-of-type
pseudo-class, which represents the first element among siblings of its element type. This answerexplains, with illustrations, the difference between :first-child
and :first-of-type
. However, as with :first-child
, it does not look at any other conditions or attributes. In HTML, the element type is represented by the tag name. In the question, that type is p
.
选择器级别 3 引入了一个:first-of-type
伪类,它表示其元素类型的兄弟元素中的第一个元素。这个答案解释,图文并茂,之间的差异: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. One workaround that Lea Verouand I came up with for this (albeit totally independently) is to first apply your desired styles to allyour elements with that class:
不幸的是,没有类似的: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;
}
... then "undo" the styles for elements with the class that come after the first one, using the general sibling combinator ~
in an overriding rule:
...然后在覆盖规则中使用通用同级组合子“撤消”具有第一个之后的类的元素的样式:~
/*
* Select all but the first .red child of .home,
* and remove the border from the previous rule.
*/
.home > .red ~ .red {
border: none;
}
Now only the first element with class="red"
will have a border.
现在只有第一个元素class="red"
有边框。
Here's an illustration of how the rules are applied:
下面是如何应用规则的说明:
<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>
No rules are applied; no border is rendered.
This element does not have the classred
, so it's skipped.Only the first rule is applied; a red border is rendered.
This element has the classred
, but it's not preceded by any elements with the classred
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 classred
. It is also preceded by at least one other element with the classred
. Thus both rules are applied, and the secondborder
declaration overrides the first, thereby "undoing" it, so to speak.
不适用任何规则;不渲染边框。
这个元素没有 classred
,所以它被跳过了。只应用第一条规则;呈现红色边框。
这个元素有 classred
,但它的red
父元素中没有任何具有 class 的元素。因此不应用第二条规则,只应用第一条规则,元素保持其边框。两条规则都适用;不渲染边框。
这个元素有类red
。它前面还至少有一个其他具有 class 的元素red
。因此,两个规则都被应用,第二个border
声明覆盖了第一个,从而“撤消”了它,可以这么说。
As a bonus, although it was introduced in Selectors 3, the general sibling combinator is actually pretty well-supported by IE7 and newer, unlike :first-of-type
and :nth-of-type()
which are only supported by IE9 onward. If you need good browser support, you're in luck.
作为奖励,虽然它是在 Selectors 3 中引入的,但一般的兄弟组合器实际上在 IE7 和更新版本中得到了很好的支持,与IE9 以后只支持:first-of-type
和不同:nth-of-type()
。如果您需要良好的浏览器支持,那么您很幸运。
In fact, the fact that the sibling combinator is the only important component in this technique, andit has such amazing browser support, makes this technique very versatile — you can adapt it for filtering elements by other things, besides class selectors:
事实上,兄弟组合器是这项技术中唯一重要的组件,而且它拥有如此惊人的浏览器支持,这使得这项技术非常通用——除了类选择器之外,您还可以调整它以通过其他东西过滤元素:
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 here 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 selectorsor any other simple selectors instead of classes.
You can also combine this overriding technique with pseudo-elementseven though pseudo-elements technically aren't simple selectors.
您可以使用它
: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 */ }
您可以按属性选择器或任何其他简单选择器而不是类进行过滤。
您还可以将此覆盖技术与伪元素结合使用,即使伪元素在技术上不是简单的选择器。
Note that in order for this to work, you will need to know in advance what the default styles will be for your other sibling elements so you can override the first rule. Additionally, since this involves overriding rules in CSS, you can't achieve the same thing with a single selector for use with the Selectors API, or Selenium's CSS locators.
请注意,为了使其工作,您需要提前知道其他同级元素的默认样式是什么,以便您可以覆盖第一条规则。此外,由于这涉及 CSS 中的覆盖规则,因此您无法通过与Selectors API或Selenium的 CSS 定位器一起使用的单个选择器来实现相同的功能。
It's worth mentioning that Selectors 4 introduces an extension to the :nth-child()
notation(originally an entirely new pseudo-class called :nth-match()
), which will allow you to use something like :nth-child(1 of .red)
in lieu of a hypothetical .red:first-of-class
. Being a relatively recent proposal, there aren't enough interoperable implementations for it to be usable in production sites yet. Hopefully this will change soon. In the meantime, the workaround I've suggested should work for most cases.
值得一提的是,Selectors 4 引入了对:nth-child()
符号的扩展(最初是一个名为 的全新伪类:nth-match()
),这将允许您使用类似的东西:nth-child(1 of .red)
来代替假设的.red:first-of-class
. 作为一个相对较新的提议,目前还没有足够的可互操作的实现来使其在生产站点中可用。希望这会很快改变。同时,我建议的解决方法应该适用于大多数情况。
Keep in mind that this answer assumes that the question is looking for every first child element that has 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:
请记住,此答案假定问题正在寻找具有给定类的每个第一个子元素。对于整个文档中复杂选择器的第 n 次匹配,既没有伪类,也没有通用 CSS 解决方案——解决方案是否存在在很大程度上取决于文档结构。jQuery 提供:eq()
、:first
、:last
和更多用于此目的,但再次注意它们的功能与:nth-child()
et al非常不同。使用 Selectors API,您可以使用document.querySelector()
获取第一个匹配项:
var first = document.querySelector('.home > .red');
Or use document.querySelectorAll()
with an indexer to pick any specific match:
或document.querySelectorAll()
与索引器一起使用以选择任何特定匹配项:
var redElements = document.querySelectorAll('.home > .red');
var first = redElements[0];
var second = redElements[1];
// etc
Although the .red:nth-of-type(1)
solution in the original accepted answer by Philip Daubmeierworks (which was originally written by Martynbut deleted since), it does not behave the way you'd expect it to.
尽管Philip Daubmeier.red:nth-of-type(1)
最初接受的答案中的解决方案有效(最初由Martyn编写但此后被删除),但它的行为并不像您期望的那样。
For example, if you only wanted to select the p
in your original markup:
例如,如果您只想p
在原始标记中选择:
<p class="red"></p>
<div class="red"></div>
... then you can't use .red:first-of-type
(equivalent to .red:nth-of-type(1)
), because each element is the first (and only) one of its type (p
and div
respectively), so bothwill be matched by the selector.
...那么您不能使用.red:first-of-type
(相当于.red:nth-of-type(1)
),因为每个元素都是其类型中的第一个(也是唯一一个)(分别是p
和div
),因此选择器将匹配两者。
When the first element of a certain class is also the first of its type, the pseudo-class will work, but this happens only by coincidence. This behavior is demonstrated in Philip's answer. The moment you stick in an element of the same type before this element, the selector will fail. Taking the updated markup:
当某个类的第一个元素也是其类型的第一个元素时,伪类将起作用,但这只是巧合。这种行为在菲利普的回答中得到了证明。在此元素之前插入相同类型的元素的那一刻,选择器将失败。采用更新的标记:
<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>
Applying a rule with .red:first-of-type
will work, but once you add another p
without the class:
应用规则 with.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>
... the selector will immediately fail, because the first .red
element is now the secondp
element.
...选择器将立即失败,因为第一个.red
元素现在是第二个p
元素。
回答by Philip Daubmeier
The :first-child
selector is intended, like the name says, to select the first child of a parent tag. The children have to be embedded in the same parent tag. Your exact example will work (Just tried it here):
该:first-child
选择的目的是,像它的名字说,选择父标签的第一个孩子。孩子必须嵌入在同一个父标签中。您的确切示例将起作用(只是在此处尝试过):
<body>
<p class="red">first</p>
<div class="red">second</div>
</body>
Maybe you have nested your tags in different parent tags? Are your tags of class red
really the first tags under the parent?
也许您将标签嵌套在不同的父标签中?你的 class 标签red
真的是父级下的第一个标签吗?
Notice also that this doesnt only apply to the first such tag in the whole document, but everytime a new parent is wrapped around it, like:
还要注意,这不仅适用于整个文档中的第一个这样的标签,而且每次都有一个新的父级围绕它,例如:
<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
and third
will be red then.
first
然后third
会变红。
Update:
更新:
I dont know why martyn deleted his answer, but he had the solution, the :nth-of-type
selector:
我不知道为什么 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>
Credits to Martyn. More infos for example here. Be aware that this is a CSS 3 selector, therefore not all browsers will recognize it (e.g. IE8 or older).
归功于马丁。例如这里的更多信息。请注意,这是一个 CSS 3 选择器,因此并非所有浏览器都能识别它(例如 IE8 或更早版本)。
回答by SamGoody
The correct answer is:
正确答案是:
.red:first-child, :not(.red) + .red { border:5px solid red }
Part I: If element is first to its parent and has class "red", it shall get border.
Part II: If ".red" element is not first to its parent, but is immediately following an element without class ".red", it shall also deserve the honor of said border.
第一部分:如果元素是其父元素的第一个并且具有“红色”类,它将获得边框。
第二部分:如果“.red”元素不是它的父元素的第一个元素,而是紧跟在一个没有“.red”类的元素之后,它也应该得到上述边框的尊重。
Philip Daubmeier's answer, while accepted, is not correct - see attached fiddle.
BoltClock's answer would work, but unnecessarily defines and overwrites styles
(particularly an issue where it otherwise would inherit a different border - you don't want to declare other to border:none)
Philip Daubmeier 的回答虽然被接受,但并不正确 - 请参阅随附的小提琴。
BoltClock 的答案会起作用,但不必要地定义和覆盖样式
(特别是它会继承不同边框的问题 - 您不想将 other 声明为 border:none)
EDIT: In the event that you have "red" following non-red several times, each "first" red will get the border. To prevent that, one would need to use BoltClock's answer. See fiddle
编辑:如果您在非红色之后多次出现“红色”,则每个“第一个”红色都将获得边框。为了防止这种情况,人们需要使用 BoltClock 的答案。见小提琴
回答by Nerdroid
you could use first-of-type
or nth-of-type(1)
你可以使用first-of-type
或nth-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>
回答by Gabriel Fair
The above answers are too complex.
上面的答案太复杂了。
.class:first-of-type { }
This will select the first-type of class. MDN Source
这将选择第一种类。MDN 来源
回答by Chetan Sastry
To match your selector, the element must have a class name of red
and must be the first child of its parent.
要匹配您的选择器,元素的类名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>
回答by Nick Craver
Since the other answers cover what's wrongwith it, I'll try the other half, how to fix it. Unfortunately, I don't know that you have a CSS onlysolution here, at least not that I can think of. There are some other options though....
由于其他的答案包括什么是错的吧,我会尽力的另一半,如何解决它。不幸的是,我不知道您在这里只有 CSS解决方案,至少不是我能想到的。不过还有一些其他的选择......
Assign a
first
class to the element when you generate it, like this:<p class="red first"></p> <div class="red"></div>
CSS:
.first.red { border:5px solid red; }
This CSS only matches elements with both
first
andred
classes.Alternatively, do the same in JavaScript, for example here's what jQuery you would use to do this, using the same CSS as above:
$(".red:first").addClass("first");
first
生成元素时为其分配一个类,如下所示:<p class="red first"></p> <div class="red"></div>
CSS:
.first.red { border:5px solid red; }
此 CSS 仅匹配同时具有
first
和red
类的元素。或者,在 JavaScript 中执行相同的操作,例如,您将使用 jQuery 来执行此操作,使用与上述相同的 CSS:
$(".red:first").addClass("first");
回答by Yener ?rer
I got this one in my project.
我在我的项目中得到了这个。
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>
回答by StinkyCat
According to your updated problem
根据您更新的问题
<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>
how about
怎么样
.home span + .red{
border:1px solid red;
}
This will select class home, then the element spanand finally all .red elementsthat are placed immediately after span elements.
这将选择一流的家庭,则该元素跨度最后全部.red元素被span元素后立即放置。
Reference: http://www.w3schools.com/cssref/css_selectors.asp
回答by Prabhakar Undurthi
You can change your code to something like this to get it work
您可以将代码更改为这样的内容以使其正常工作
<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>
This does the job for you
这对你有用
.home span + .red{
border:3px solid green;
}
Here is a CSS reference from SnoopCodeabout that.
这是来自SnoopCode的 CSS 参考。