css⾸个元素,类的第⼀个元素的CSS选择器
⼩编典典
这是作者误解: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”边框。
这是如何应⽤规则的说明:
blah
first
second
third
fourth
没有规则适⽤;没有边框。
该元素没有class red,因此被跳过。
仅应⽤第⼀个规则;呈现红⾊边框。
该元素具有class 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多⽤于这⼀⽬的,但要注意再次证明它们的功能从⾮常不同: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
尽管d:nth-of-type(1)最初接受的答案中的解决⽅案有效(该解决⽅案最初是由Martyn编写,但此后已删除),但它的⾏为⽅式并不符合您的期望。
例如,如果您只想p在原始标记中选择:
…那么您将⽆法使⽤.red:first-of-type(等效于.red:nth-of-type(1)),因为每个元素都是其类型(p和div)中的第⼀个(也是唯⼀的)元素,因此选择器将匹配这两个元素。
当某个类的第⼀个元素也是其类型的第⼀个元素时,伪类将起作⽤,但这仅是偶然发⽣的。Philip的回答证明了这种⾏为。当您在该元素之前插⼊相同类型的元素时,选择器将失败。进⾏更新的标记:
blah
css 属性选择器first
second
third
fourth
应⽤带有的规则.red:first-of-type将起作⽤,但是⼀旦您添加了另⼀个p没有该类的规则:
blah
dummy
first
second
third
fourth
…选择器将⽴即失败,因为第⼀个.red元素现在是第⼆个 p元素。
2020-05-16
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论