您知道这些选择器之间的区别吗?
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 ~ p和div + 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;
规范
阅读一下规范以了解这些内容也不会有什么坏处。
嗨,Chris,
我知道“>”,其他的对我来说是新的。非常感谢…
附注:我一直想知道你从哪里找到时间做你所做的一切 :)
此致,Bert
Chris 从不睡觉。他可能来自另一个星球的外星人。
我不敢相信我现在才看到这篇完美的帖子。
在使用 css 很长时间后,摆脱旧习惯并学习新东西真是太好了 :)
非常感谢!!
Chris,感谢您的文章;一如既往:时机完美!看看我在几周前在 DynamicDrive 上发表的一篇博文:CSS 选择器愿望清单
它们是很酷的选择器,尤其适用于菜单样式。或突出显示列表中的第一项。我不会在它们的基础上构建我的布局。HTML 中的一个更改很容易搞砸事情。
Adobe 推出了 dreamweaver cs5,它具有很多功能,其中之一是 css 检查模式,它将处理 css 属性。
我的问题是,是否可以通过使用 dreamweaver cs5 在不详细了解它们的情况下修复 CSS 属性。我已在此处发布收集的其他主要功能 Dreamweaver CS5 的 CSS 属性和其他一些新功能
在我看来,IE6 最大的罪过是不支持这些选择器。它们非常有用,几乎没有人费心去使用它们。
也许是 IE8 最大的罪过,但不是 IE6 的。
即使谈论 IE8,我也不敢肯定它很糟糕。不可取,是的,但当你从大局来看时是可以接受的。
IE7 主要是一个功能追赶版本(据我所知)。
IE8 是一次 CSS 赶超尝试,他们试图完全支持 CSS2,并且几乎通过了 Acid2 测试。
IE9 看起来将拥有令人印象深刻的 CSS3 支持和 HTML5 支持,以及对硬件加速的支持(尽管为什么需要硬件加速还有待商榷)。
所以,虽然 IE 的发展速度不如我们所有人希望的那样快,但它*确实*在进步。
啊,我现在明白了。
不再需要 ul li ul li ul li ul li {} 了!
非常感谢 Chris,你的帖子总是很有用
这对我来说是全新的。谢谢!
这篇文章中的图片以一种非常简洁的方式解释了每个选择器的作用。
顺便问一下,为什么新的“感谢”部分没有“由 WordPress 提供支持”?我认为这是一个完美的补充,可以很好地填充该区域。
如果我错了,请纠正我,但我认为这不是正确的。
ul>li 将选择任何作为 ul 子元素的 li。
在你的例子中,你嵌套了一个 OL,但将其更改为 UL(就像你在文本中提到的那样),嵌套项 1 和 2 也将被选中。
这个例子可能有点奇怪,因为某些东西可能会级联到列表中,因为嵌套列表是该顶级列表项的子元素……但是子元素选择器实际上并没有选择较低级别的列表项。
这听起来有点像胡言乱语……以下是一个示例,其中内部 OL 的颜色为黑色,然后父列表项的颜色为红色。列表项选择器更具体,但它不会选择 OL 或 OL LI,因此颜色保持为黑色。
http://cdpn.io/qmGck
我理解链接中的示例
ol 是黑色的,所以项目符号和“test”这个词将是黑色的。但是 ol 被 li 标签包围,所以整个 ol 成为 li,它是 ul 的子元素,并且使用样式 ul>li color red,ol 将变为红色,这意味着项目符号是红色的。好的,清楚了。
在你的示例中,ol 被列表项 2 中的 li 标签包围,因此整个 ol 将以与 ul>li 相同的方式设置样式。
如果你从上述 li 标签中取出 ol,那么嵌套项 1 和 2 将不再受到影响,因为它们是 ol 的子元素。
如果你将 ol 更改为 ul,则会得到一个父 ul,它有 3 个子元素(3 个 li),其中 1 个有 1 个子元素(第二个 ul,它又包含 2 个子元素,即嵌套项)。
好的,现在 ul>li 将选择作为顶级 ul 子元素的 3 个 li,以及嵌套 ul 中的 2 个嵌套 li……
(好的,我现在头晕了。期待你的回复)
是的,我认为我理解的所有内容都是正确的=)
你是否担心使用此方法会选择嵌套列表中的所有列表项(不像我提到的那样“停止级联”?)。
如果是这种情况,我认为在一般用法中,这将与例如 ID 选择器结合使用。因此,例如 ul#main-navigation > li 只会选择那些顶级 LI,而不会选择其他嵌套 LI
是的,ID 可以解决问题,但这又回到了我的最初观点。
假设(在你的示例中)你希望 3 个顶级 li 内容的字体颜色(即文本“列表项一”、“二”和“三”)为红色。
如果你使用 ul>li,那么这 3 个 li 将变为红色,并且整个 ol(项目符号和文本“嵌套项一”和“二”)也将变为红色。
如果你将 ol 从第二个 li(内容为“列表项二”)中取出,那么实际上只有 3 个主 li 将变为红色,但这仅仅是因为嵌套 li 是 ol 的子元素。
将此 ol 更改为 ul,则 3 个主 li 的内容(文本)和 2 个嵌套 li 的内容(文本)将变为红色。
因此,级联不会在第一级停止,而是会贯穿整个过程,并查找每个作为 ul 子元素的 li,无论它嵌套多深。
@Leonardo:在那种情况下,id、类或更多上下文是你的唯一选择。
#nav > ul > li
.article > ul > li
div > ul > li
据我理解,这就是你所要求的。
Chris 本可以这样写
ul { color: red; }
ol { color: black; }
但我认为这种语言令人困惑
“换句话说,它只查看标记结构下一级,不会更深”
这是不正确的。我刚刚测试了这一点。没有任何其他样式(是的,我看到了你的 jsbin Chris,并且你正在设置 ol 的样式),它确实会深入。它将命中该 ul 中的每个 li,无论你是否使用 id/class。
你必须设置 ol 的样式才能使嵌套 li 的颜色发生变化(这正是 Chris 在 jsbin 中所做的)。
是的,即使 ol 中的 li 没有被选中,它们也会继承被选中的 ul 中的 li 获得的规则。一个更好的例子是
ul>li>a {}
<ul>
<li><a>one</a></li>
<li>
<ol>
<li><a>two</a></li>
</ol>
</li>
</ul>
这只会选中“one”。
感谢 Chris!
你提到它在现代浏览器中都受支持,那么 Safari 和 Firefox 是否都很好用?
当以某种方式设置列表样式时,这可能非常有用,我总是向项目添加类以使其外观不同,但使用显示的技术,这将不再是问题。
但是 Leonardo 在我上面提到的关于 ul>li 会选择任何作为 ul 子元素的 li 的内容,这意味着你是否必须使用另一个,而不是使用另一个?希望我表达清楚!但是,如果你要在 a 内使用 ul 并使用 ul>li,那么这肯定仍然会设置内部 ul li 的样式?
也许其他人可以帮我用更好的英语表达一下!
谢谢
非常及时且内容丰富的帖子。(希望他们会让你换一台 MBP。:-))
很棒的帖子!当然,这将节省一些代码行,但我们仍然需要很长时间才能使它成为标准,幸运的是……
查看这个交互式 jQuery 选择器测试器,你可以用它来针对你的 html 测试你的表达式。
感谢 Chris,很有见地的信息
我真的很希望有一个“父”选择器。这样你就可以选择项目的容器。当你不知道内容位于哪个容器中,但需要向该容器添加样式时,这将特别有用。
非常感谢你的帮助,但告诉我这是否适用于所有浏览器……
Chris 说
“这些在 IE 8 及更高版本以及所有其他现代浏览器中都可以正常使用。IE 7 也支持,但请注意,HTML 注释可能会破坏它们,并导致它们在兄弟元素之间不匹配。”
感谢 Chris 的文章,它非常有信息量。
我知道 >,并且经常使用它,但我从未听说过 + 和 ~。它们似乎非常有用!感谢你的提示。
很棒的文章——这些选择器以前总是让我很头疼,但现在我理解得更清楚了。
我最喜欢的 + 的用法是这样的
p{margin:0}
p + p{margin: 30px 0 0 0}
或者更漂亮
dd + dt {margin: 30px 0 0 0}
对于 >,它在 HTML5 中尤其好用,在 HTML5 中,带有类和 id 的 div 可以被漂亮的标题和页脚替换。
body > header{color:white;}
article > header{color:blue;}
实际上,有用的示例数量是无限的。
我读到这些选择器会使你的 CSS 变慢。但我怀疑任何人都能看出快速 CSS 和快速 CSS 之间的区别(CSS 总是很快的)。
ul > li 实际上比 ul li 快
酷,我以前不知道相邻兄弟选择器,这对避免大型 CSS 文件中充满上下文规则很有用。
你好 Chris,这篇文章有点让人困惑。如果你能用更简单的方式叙述一下,那就太好了。
感谢提供如此棒的 CSS 技巧。
我之前真的不知道 >、+ 和 ~ 的用法。
谢谢,并请继续保持这种良好的工作状态。
:)
这篇文章已经6年了。。
不管它有多旧,很多人都不使用它,Chris 只是在向那些不知道的人传授知识。这些选择器真的很棒,所以如果你知道它们,那很好,但我们并非所有人都知道。
我花了一段时间才学会使用 >,我会尝试更多地使用 +,尽管我使用一些带有属性选择器的其他选择器。
不错的文章。感谢你的所有努力。
无法使用“父元素”选择器的原因是 CSS 限制了只能使用一次遍历算法。
当浏览器解析 CSS 选择器时,它可以通过精确遍历每个元素一次来将样式应用于每个元素。如果允许使用父元素选择器,解析器将需要回溯 XML 树,这将导致速度呈指数级下降。
借助高级选择器可以完成所有这些事情,这真是令人难以置信。正如你推荐的 ie7.project,我脑海中突然冒出几个问题。
1. 为什么人们仍然害怕使用此类脚本?
2. 这些脚本可能对你的网站造成什么严重影响?
3. 这是让浏览器按你意愿执行操作的真正/正确方法吗?
我真的很困惑
太棒了!这篇文章真的帮助了我们。而且 ie7-js 项目也非常有用。我开始在这里测试它。感谢你的努力。
这篇文章一如既往地教会了我一些东西,我已立即在一个最近的项目中开始使用它,再次感谢 Chris!!!
这是一篇非常非常有帮助的文章,非常非常感谢!
“我之前说过很多次了,但在 CSS 中,主要缺少的选择器样式是某种“包含”(或“拥有”或“限定”或任何你想要称呼它的名称)。“
我没有详细研究过这个主题,但我理解这会违反级联本身的概念,因此不在考虑范围内。我使用 jQuery 选择包含图像的锚点(以去除下边框)。
确实,所有 div 但对 ID 属性进行过滤
div.myClass => 所有 div 但对 class 属性进行过滤
a[title] => 所有链接但对 title 属性的存在进行过滤
因此我们可以很容易地想象类似于对内容进行过滤
p[所有段落但对 img 的存在进行过滤
谢谢 Chris!我之前见过很多次这些选择器,但不得不承认我比较懒,从未花时间去理解它们到底在做什么。这些在将来会非常有用。我可能会在我的新网站上尝试使用它们。
我在使用子元素选择器时取得了喜忧参半的成功,这主要是由于 IE6 和 IE7 的问题。
我尝试了 IE7.js 和 IE8.js,但它们当时都显得有点有错误,并且在包含后导致了更多不稳定的行为。
由于某种原因,它完全无法处理某些绝对和相对定位的元素,导致在 IE6 中完全无法显示 html 块,没有任何明显的原因。我最终不得不放弃 JS 包含,而是使用条件包含的 ie6.css 文件。
当我不需要为 ie6 制作 css 时,我总是使用这些选择器。因为它们使代码更容易阅读(css 和 html)。
我知道我错过了比赛的最佳时机……但我创建了一篇快速的文章,其中说明了 Chris 在这里没有列出的其他一些花哨的 css3 选择器。
谢谢!:D
这非常有帮助,我自己无法解决,也没有时间进行测试。
我想知道,为什么有相邻兄弟选择器,却没有 nth-sibling 选择器?
例如,让我们考虑这种情况
那么,如果你只想选择中间的 p,但仅在 div.only-after-me 之后(据我所知,目前这不可能)?
它将类似于此(或者我想听取建议)
div.only-after-me + p:nth-sibling(2)
其中仅使用 p:nth-sibling(2) 将选择在任何元素之后出现的每个第二个 p。
这不会违反从右到左的渲染和内存问题,因此我很好奇是否之前有人向 CSS 草案提出了这个建议以及为什么被拒绝,如果还没有提出,为什么没有?
Chris,我非常感谢你的工作,并希望听取你的意见并讨论这个话题。
谢谢
这些图表对于学习选择器之间的区别至关重要,解释起来可能会非常混乱。