不,你不能。
在可预见的未来也不要指望它。让我们来看看为什么!
从从事 CSS 引擎工作的人的角度来看,选择器实际上是向后评估。这当然是 CSS 的一个相当有趣且鲜为人知的方面。虽然 CSS 选择器规范没有直接定义实现行为,但所有选择器的定义都考虑到了这一点。没有创建可以在 DOM 中任意跳转的分层/“结构”选择器,因为与我们今天的相比,这会导致严重的性能问题。
因此,例如,让我们采用以下选择器:
#target:hover .effect
这要求类为 effect 的元素是 ID 为 target 的元素的子元素(在任何深度),因为选择器引擎以 匹配开始首先是 effect 类的元素,然后继续向后工作,在 DOM 中逐步查找 ID 为 target 的父元素。
跳转到父节点非常快。向前评估这一点将涉及测试 ID 为 target 的任何元素的所有子元素,这会大大提高性能。
CSS 评估的这一特性自然对性能很重要;在最坏的情况下,上面的选择器只会冒泡到 DOM 的根,一路上只测试少数元素。例如,直接子选择器a > b 仅测试直接父然后停止。
“烘焙”选择器的结构
为了进一步提高性能,选择器的 结构 被“烘焙”到 DOM 中。 There certainly isn't consensus on this, i.e. every CSS engine does it differently, but roughly when the DOM structure of a selector matches (i.e. we have found an element with a class of effect and any parent with an id target) 选择器被记录为在 DOM 中匹配,无论 #target 上的悬停状态如何。当#target 上的悬停状态发生变化时,它会简单地碰撞在元素处烘焙的所有选择器 - 这可能会触发整个选择器激活或停用。这样我们就不会在鼠标四处移动时不断测试大量元素。
简而言之,如果它可以随意在 DOM 周围跳跃,那么这些都不起作用。进入/离开 DOM 的元素可能会影响 DOM 完全独立部分中的选择器,因此样式引擎可能会检查整个 DOM 以使该索引保持最新。
部分加载的 DOM
还考虑到我们可以测试元素 before,但不能测试 after(当向后评估时):
h1 + h2
h1 - h2 /* ..? Doesn't exist! */
这是因为当我们从一个“h2”元素开始测试这个特定的选择器时,它后面的 DOM可能实际上还没有被加载。一旦一个元素进入 DOM,无论是因为它刚刚从传入的 HTML 中解析出来,或者它是通过脚本添加的,我们就开始检查它匹配的选择器。这意味着我们不能依赖原始 HTML 中元素之后的任何可用内容,所以这也是任何 DOM 跳跃的块。
总结
目前不可能,也不太可能很快添加,因为它会使 CSS 实现的多个性能特征失效。这并不是说它不会被添加; W3C 确实意识到硬件变得越来越强大,因此总有一点让作者的便利性胜过实现性能的考虑。
因此,将这一点进一步放在问题的上下文中,请查看this fiddle created by @Marvin 以了解当前选择器的可能性。