具有类的第一个元素的CSS选择器
我有一堆类名为red
的元素,我似乎无法使用以下CSS规则选择class="red"
的第一个元素:
.red:first-child{
border:5px solid red;
}
<p class="red"></p>
<div class="red"></div>
这是作者误解如何的最着名的例子之一:first-child
作品。 在CSS2中引入的:first-child
伪类代表了其父代的第一个孩子 。 而已。 有一个非常常见的错误观念认为它会选择哪个子元素首先匹配其余复合选择器指定的条件。 由于选择器的工作方式(请参阅这里作为解释),这根本不是事实。
选择器级别3引入了:first-of-type
伪类,它表示元素类型的同胞中的第一个元素。 这个答案用插图解释了:first-child
和:first-of-type
:first-child
之间的区别。 但是,与:first-child
,它没有考虑任何其他条件或属性。 在HTML中,元素类型由标签名称表示。 在这个问题中,这种类型是p
。
不幸的是,没有类似的:first-of-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;
}
...然后在一个覆盖规则中使用常规兄弟组合符~
来“撤销”具有第一个类之后的类的元素的样式:
/*
* 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>
没有规则适用; 没有边框被渲染。
这个元素没有red
的类,所以它被跳过。
只有第一条规则适用; 呈现红色边框。
此元素具有red
类别,但不在其父级中具有red
类别的任何元素之前。 因此,第二个规则不适用,只有第一个,并且该元素保持其边界。
两条规则都适用; 没有边框被渲染。
这个元素的类是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 API或Selenium的CSS定位器一样的功能。
值得一提的是,选择器4引入了对:nth-child()
符号的扩展(最初是一个全新的伪类,称为:nth-match()
),它将允许您使用类似如下的东西:nth-child(1 of .red)
代替假想的.red:first-of-class
。 作为一个相对较新的提案,还没有足够的可互操作的实现方式使其可以在生产站点使用。 希望这会很快改变。 同时,我建议的解决方法应该适用于大多数情况。
请记住,这个答案假定问题是寻找每个具有给定类的第一个子元素。 对于整个文档中复杂选择器的第n次匹配,既没有伪类也没有通用的CSS解决方案 - 是否存在解决方案在很大程度上取决于文档结构。 jQuery为此提供了:eq()
:first
, :last
和more,但是再次注意到它们的功能与以下内容非常不同:nth-child()
等。 使用选择器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最初接受的答案(最初由Martyn编写但自此之后删除)的答案中的.red .red:nth-of-type(1)
解决方案,但其行为并不像您期望的那样。
例如,如果您只想在原始标记中选择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
元素。
第: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
选择器:
<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。 更多信息例如在这里。 请注意,这是一个CSS 3选择器,因此并非所有的浏览器都会识别它(例如IE8或更早的版本)。
正确答案是:
.red:first-child, :not(.red) + .red { border:5px solid red }
第一部分:如果元素是第一个到它的父级,并且类为“红色”,它将得到边界。
第二部分:如果“.red”元素不是第一个给它的父亲,而是紧接着一个没有“.red”类的元素,那么它也应该得到这个边界的荣誉。
小提琴或它没有发生。
Philip Daubmeier的回答虽然被接受,但并不正确 - 请看附带的小提琴。
BoltClock的答案会奏效,但不必要地定义和覆盖样式
(特别是否则会继承不同边界的问题 - 您不希望将其他边界声明为无:)
编辑:如果您多次使用非红色的“红色”,则每个“第一个”红色都会显示边框。 为了防止这种情况,需要使用BoltClock的答案。 看小提琴
链接地址: http://www.djcxy.com/p/3905.html