子元素和兄弟元素选择器

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

您知道这些选择器之间的区别吗?

ul li { margin: 0 0 5px 0; }
ul > li { margin: 0 0 5px 0; }

我承认,当我学习 CSS 基础知识时(很久以前),我花的时间比应该花的时间长得多。在这两种情况下,它们都在选择作为无序列表子元素的列表项。但子元素后代元素之间存在区别。

上面第一个选择器是后代选择器。它将选择标记结构中无序列表下任何位置的列表项。列表项可能嵌套在其他列表中三层深,此选择器仍将匹配它。上面第二个选择器是子元素组合选择器。这意味着它只选择作为无序列表直接子元素的列表项。换句话说,它只查看标记结构一层,而不是更深。因此,如果存在嵌套更深的另一个无序列表,则其列表项子元素将不会被此选择器选中。

我认为每个人都理解基本的后代选择器,但让我们快速概述一下这种风格的其他选择器:子元素组合选择器相邻兄弟组合选择器通用兄弟组合选择器

子元素组合选择器

我们在本文的介绍中介绍了这个。让我们用一个视觉效果来巩固同一个例子。

我认为嵌套列表是此选择器有用的一个完美示例。可以将其视为一种防止样式级联超出您希望范围的方法。也许您想使最外层的列表项变大并类似标题,但嵌套列表变小并更像正文内容。使用子元素组合选择器,您可以仅选择那些顶级列表项,而不必担心大型/标题样式级联到嵌套列表并必须与该样式作斗争。

相邻兄弟组合选择器

一个相邻兄弟组合选择器允许您选择紧跟在另一个特定元素之后的元素。

p + p { font-size: smaller; } /* Selects all paragraphs that follow another paragraph */
#title + ul { margin-top: 0; } /* Selects an unordered list that directly follows the element with ID title */

这些选择器可以帮助您以上下文的方式应用样式。也许您在网站上有一堆文章。它们中的大多数以<p>元素开头,看起来很棒。但有些以<ul>开头,在您的网站上具有顶部和底部边距,以便在文章中看起来不错。但是,当它们开始一篇文章时,会导致出现尴尬的间隙。上面后面的选择器将在文章开头(紧跟标题之后)将该顶部边距清零。

希望有帮助的图形

通用兄弟组合选择器

通用兄弟组合选择器与我们刚刚看到的相邻兄弟组合选择器非常相似。不同之处在于被选中的元素不需要紧跟第一个元素,而是可以出现在其后的任何位置。

如果我们使用与上面相同的示例结构,则最后一个<p>元素将被p ~ p也选中,因为它前面有另一个<p>元素,即使不是直接的。

请注意,在通用兄弟选择器和相邻兄弟选择器中,逻辑都在同一个父元素内发生。这就是兄弟姐妹的含义……共享同一个父元素。在上面的图形示例中,这就是<div>包装器的作用。如果在该<div>之后还有另一个<p>元素,它仍然会被两者选中div ~ pdiv + p尽管如此,因为它将是该<div>的兄弟元素和相邻兄弟元素。

浏览器支持

这些在 IE 8 及更高版本以及所有其他现代浏览器中都可以正常使用。IE 7 也支持,但请注意,HTML 注释可能会破坏它们并导致它们在兄弟元素之间不匹配。

如果您需要比这更深层次的支持,则ie7-js 项目(现在已更新到 ie9.js)将让您获得对所有这些的支持,甚至可以追溯到 IE 5.5,只需包含一个简单的 JavaScript 文件即可。

许个愿

我之前说过很多次了,但在 CSS 中缺少的主要选择器样式之一是某种“包含”(或“拥有”或“限定”或任何您想称呼它的名称)。这个想法就像“选择所有包含图像的段落”。

可能是这样的

p < img { width: 150%; } /* Not real! */

显然,当权者出于某些复杂的原因(我认为与速度有关)拒绝了它很多次。jQuery 可以做到

$("p:has(img)")

并且甚至可以调整以使用“<”语法

jQuery.parse.push(/^\s*(<)(\s*)(.*)$/);
jQuery.expr["<"] = jQuery.expr[":"].has;

规范

阅读一下规范以了解这些内容也不会有什么坏处。