让我们在此明确一点,以防有人通过搜索引擎找到此处:CSS 中没有父选择器,即使在 CSS3 中也没有。不过,这是一个有趣的讨论话题,并且最近又出现了一些新的讨论。
早在 2008 年,Shaun Inman 建议 使用以下语法
a < img { border: none; }
[更正以下句子]:在此示例中,它将选择 a
标签,但前提是它们包含 img
标签。(旁注:这将偏离典型的语法,在典型语法中,实际被选中的元素位于右侧,而这里则位于左侧)。
一定要阅读该帖子中的评论,这是一个非常有趣的讨论串,其中包含了父选择器至今不存在的一些相当重要的原因。David Hyatt 是 WebKit 中实施此类功能的前线开发人员,他评论道
使用父选择器,很容易意外地导致文档范围内的遍历。人们可以并且将会误用此选择器。支持它就是在给人们很多绳子让他们上吊。
Jonathan Snook 重新提出了这个话题,并为我们提供了有关 CSS 渲染工作原理的大量背景信息。我们都听说过通用选择器是最没有效率的 CSS 选择器。Jonathan 表示,如果存在父选择器,那么它将轻松成为新的效率最低的选择器。论点是,当元素动态地添加到页面或从页面中移除时,可能会导致需要重新渲染整个文档(主要的内存使用问题)。不过,Jonathan 仍然乐观
我描述的并非技术上不可能。事实上,恰恰相反。这仅仅意味着我们必须处理使用此类功能带来的性能影响。
Remy Sharp 也加入了这场有趣的讨论,并建议使用以下语法
a img:parent { background: none; }
关键区别在于,:parent 语法只会评估单个元素,即 DOM 中每个元素可用的 parentNode
。这类似于强制 :has 选择器仅评估子元素,而不是所有后代元素。
到目前为止,每个人都达成一致
- 存在巨大的性能问题
- 这些问题可以被视为我们应该评估的权衡,而不是障碍。
- 想要!
不错的文章,我个人不需要父选择器。如果它会带来性能问题,我认为它不应该出现在规范中。
但是,嘿,如果你,Chris,CSS 大师,能够提出一些父选择器可以使事情变得更容易的场景。我很乐意听听。
我同意,我想看看一个父选择器至关重要、使事情变得更容易或更高效(如果不存在性能问题)的场景。
Rick –
我昨天遇到了一个——我正在为一个从 CMS 自动生成的导航进行样式设置(因此我无法向标记中添加类或 ID,并且导航链接的顺序可能会随着时间的推移而改变,因此我无法使用 :nth 选择器)。
我希望包含 URL http://foo.com 的导航看起来有点不同。如果能够使用类似于 li < a[href=http://foo.com] {background:red} 的东西,那就太好了。
这确实是一个可以使用父选择器的很好的例子。但是,您是要为“a”还是“li”设置样式?因为如果您想为“a”设置样式,您可以忽略它包含在“li”中的事实,并执行以下操作。
a[href=http://foo.com]{//样式}
除非您只想在特定位置为“a”设置样式,而不想在网站的其他位置设置样式。然后,您应该使用以下要求对其进行限制
#header a[href=http://foo.com]{//样式}
在设置悬停样式时,能够在选中子元素时使父元素做出反应会很好。
父选择器的一个很好的理由是在设置单选按钮或复选框的样式时。出于某种原因,Firefox 不喜欢为单选按钮和复选框之类的输入元素设置背景。我有一个项目,其中我使用了看起来像“是/否”按钮的单选按钮(有利于辅助功能),并在输入上使用了 :checked,从而在按钮周围添加了边框。
但是,这在 FF 中不起作用。我看到的只是实际的单选按钮或复选框。要为输入元素设置样式,我确实需要将其放在一个 div 标签内并为其设置样式,但随后会出现一个问题,即在选中时如何在它周围添加边框,因此;父选择器很有用!
我看到“!”作为 CSS4 草案,所以在我的情况下,执行以下操作会很好
Div! > input[type=radio]:checked { border: 2px solid #000; }
当输入元素被选中时,div 将获得边框。
感谢提示,很有用。
我看不到它的实际用途。
a < img
和a > img
不是一回事吗?我想 Chris 打错了字。
使用建议的语法,“a < img”将选择具有“IMG”后代的“A”。
更好的表达方式是“父选择器包含后代选择器”,其中您将“包含”替换为“<”。
Shaun 描述的方式确实与我所说的相反,但我认为它可以以任何一种方式工作。我个人更喜欢我描述的方式,这意味着选择器最右侧的部分仍然是实际被选中的元素,而不是最左侧的部分。
想想一个多级下拉菜单。一些 LI 也包含另一个 UL,但有些则没有。能够仅定位那些是另一个级别的父级的 LI 会很酷,这样您就可以例如应用一个箭头指示器,表示此列表项包含一个子菜单。现在没有您可以编写的选择器来定位包含 UL 的 LI。
您可以在服务器端为父 LI 添加一个类来实现此目的。
您可以。您也可以让服务器分析所有内容的外观,并根据需要将内联样式应用于每个元素。因为存在一些解决方法,并不意味着 CSS 应该保持中立。
@Phil:出于好奇,您将如何实现此目的?您如何使用服务器端方法为父 LI 提供一个类,因为它们具有子 UL?使用 jQuery 执行此操作非常简单,尽管我不知道您可以在服务器端执行此操作。
是否有“hasClass”PHP 语法?
@Amit,不,不是那种意义上的,例如,如果您正在通过运行循环或递归函数输出一个有多个级别的菜单,那么您将知道顶级 LI 具有子级,并且可以向其添加一个类。
@chris,我没有任何时候建议添加内联样式。为什么要在服务器上分析任何内容的外观?我认为这不是解决方法,而是您给出的场景的解决方案。
a < img
选择器实际上表示“如果 a 具有子级 img,则选择 a”。父选择器在许多领域都非常有用——例如div < input.error
(这样,如果您想显示验证错误,则不必将错误类定义重复到 div 或更高级别的父元素)。a < img { border: none; }
在此示例中,它将选择img标签,但前提是它们是a标签的子级。
而不是您所说的,上面(建议的)代码将选择一个a标签,但前提是它是img标签的父级。您建议的内容已被以下内容涵盖
a img { ... }
我认为…
不,不是。因为(大多数(较旧的)版本的 Internet Explorer)默认情况下会为<a>元素应用样式,即图像的边框和文本的下划线。您必须定位 a 元素。
但是假设您希望在“普通”链接下方有一条漂亮的点线,您现在无法轻松地做到这一点,但是可以使用父选择器
Chris,很棒的文章,感谢你的提示!
记住,这并不是一个真正的“提示”,它目前还不存在,所以不要急着尝试使用它!
它曾经在CSS3中,但后来被移除:http://www.w3.org/TR/css3-selectors/#content-selectors
(a:contains(img))
我不确定,但我认为:contains是一个内容选择器,它实际上读取节点中的文本并根据文本进行选择。因此,例如,您可以突出显示包含特定单词的特定段落…
我认为父选择器在某些时候会派上用场,但在大多数情况下,你应该能够使用更有效的方法。
我很少在JavaScript中使用父选择器(在我看来,jQuery做得相当不错),但我尽量避免使用。
我明白你的意思,Chris,我喜欢这个想法。现在,如果有人能把它规范到CSS4或其他什么地方就好了。
我能理解父选择器在什么地方有用,例如,你可以在特定元素之后只更改h1的边距或颜色。
也许这可以放在未来功能的“CSS愿望清单”下——尽管如果存在冲突规则,则会增加特异性的复杂性。
好吧,父选择器可能派上用场,但它们也需要支持一些伪类。
例如,假设你的菜单是这样的:div > ul#menu > li*3 > a
并且你想让div或li在a:hover或a:focus时更改背景,使用父选择器,你可以这样做
li < a:hover, li <a:focus {background:red;}
现在,你可以通过JavaScript或将悬停应用于li元素来实现这一点。
我同意,正如Jonathan所说,这将导致严重的性能问题,也许浏览器可以通过内部JavaScript来应用它,这样就不会影响性能,但它不会完全是一个CSS解析器。
我并不介意没有它..但正如我所说..它可能会派上用场..
太好了
它比使用JavaScript getParent()更好
它可以多次使用吗,例如li:parent:parent?
在我看来,是的。
无论语法是“li < ul”,“ul < li”还是“li:parent”,我认为都应该始终可以多次执行此操作,在这种情况下,“<”更灵活。
当然,如果你认为“<”语法需要知道元素标签名而“:parent”不需要,那么你就错了。因为我们也可以使用“*”
“* < tag”和“tag < *”
是的,我们可能仍然缺少像这样的有趣的东西,因为已经提出了各种可能性。
嗯,是的,在少数情况下你需要这个,只需添加一点JS
例如 http://pastie.org/849838
这可能只是个人偏好,但我认为以下语法更有意义,尤其是在更复杂的样式选择器中
img < a
而不是
a < img
为什么?因为在其他每个CSS选择器中,最后一个元素描述的是要设置样式的内容。在这种情况下,我们希望在a具有img子元素时设置a的样式,所以将其放在末尾更有意义(同样,我猜这只是个人偏好)。
当使用更深层次的选择器时,这可能会变得非常复杂,但我喜欢它。我还记得在最近的一个项目中希望它存在。
这可能有利于阐明伪类
a:hover < img 似乎表明当子元素a悬停时,img样式将发生变化,而不是img < a:hover
我也同意“img < a”用于选择图像的锚点父元素更有意义。
我不是第一个说这句话的人,但我认为在第一个示例中,你的意思是“只有当它们是
a
标签的父元素时”…或者不是?你让我困惑了一段时间:)你知道吗,我确实搞砸了。我现在已经修复了。
嗯…我的英语不太好,但我同意伊万的观点:示例和解释与文章主题不符(你可能打错了字)。
我指的是
a < img { border: none; }
和
“在这个例子中,它会选择img标签,但前提是它们是a标签的子元素。”
因为还有
a img { border:none }
仅当img标签是a标签的子元素时才会选择它。
相反,一个更好的例子是
ul < li { padding-left:0px; }
它会移除所有包含另一个ul级别的li标签的左侧填充
所以在多级菜单中,所有具有子菜单的项目。
ul li:hover a { background-color: #000000; }
ul < li:hover { background-color: #cc0000; }
突出显示子链接的悬停是可以的,但在与子元素(例如悬停)交互时,也应该能够突出显示无序列表的背景。
我们都记得使用CSS设置表格和输入元素样式时受到限制…我相信这样做的理由也很充分,但这并不意味着我们需要永远忍受它…所以我们没有。
父选择器可能也并无不同。
好在我们有jQuery可以使用“:has”选择器来模拟它,但很遗憾,不得不使用服务器端或JavaScript来实现一些本来在真正的CSS中很容易实现的东西。
仅仅因为人们能够滥用某些东西,并不是使该选择器失效的理由:人们已经非常有能力滥用现有的选择器了。
不得不使用服务器端脚本或JavaScript来模拟父选择器,就像你被迫使用JavaScript添加一个类来模拟IE6中的悬停选择器一样: (
此外,已经存在被滥用的文档级选择器:例如,有多少网站使用“*”?它的范围比父选择器要大得多。
除了:has之外,jQuery还有.parent(); 两者都有其优缺点。
“在这个例子中,它会选择img标签,但前提是它们是a标签的子元素。”
我认为它只会选择a标签,前提是它们是img标签的父元素..
哦,你已经修复了:)
根据经验,我认为设计师不需要父选择器,事实上,我认为如果引入了它,我会觉得很沮丧。与重置样式表类似,我不使用这些,因为我了解浏览器的运作方式并相应地进行补偿。
在语句中使用感叹号标记要设置样式的元素怎么样?
a > img 选择从链接派生的图像
a > img! 将相同。
a! > img 然而,将是从这些图像派生的链接。
我意识到,在我思考之后,这与img 非常相似,它将匹配与a > img 相同的所有内容,它只会将样式应用到匹配项的上一级。使这一点明确将使阅读和编写这些样式变得更加简单。
实际上,通过不在与> 或+ 或其他任何内容相同的级别上作为选择器,我们可以使用现有选择器的全部范围作为我们的限定符。
在“限定选择器”中,并没有完全清楚“<”的作用。div < img 是否匹配中的div?我认为他说是的,但如果是,是否可以用一个*不*以后代选择器开头的语句来限定选择器?如果不是,如何编写一个可以执行此操作的选择器?
使用. 即使可以实现,div img 也非常糟糕。
感叹号与“关系”选择器(,)明显不同,它们应该附加到“独立”选择器(类、ID、类型和伪选择器)上,以阐明其用法
blockquote! img
blockquote! > img
blockquote! + img
div! > :checked
我喜欢这个,我之前也在想用括号“圈住”选中的元素。
这是一个很棒的想法!不确定使用哪个字符最好,但这解决了最后一个元素不代表要设置样式的元素的许多问题,也避免了之前我提到的反向标记的混淆。我投票支持 $ 而不是 !,因为美元符号类似于“S”,代表“设置此元素的样式”。
div > a$ > img
寥寥数语,却道出了许多。很棒的文章,Chris。
如果性能不是问题,我真的很喜欢这个概念。
很多时候我想设置包含图像的链接的样式,而添加类很麻烦。
在这种情况下使用它会很棒,但是,我觉得语法应该是
img < a 而不是 a img,后者是 a 标签内的图像,我想要 img < a,即 a 标签包裹着图像。
我认为最好将选定的元素保留在右侧,为了保持一致性。img:parent(figure) 将匹配 img 的所有祖先 figure 元素。img:nth-parent(2) 将选择 img 的祖父元素。img:parent 将选择所有祖先。img:nth-parent(1):filter(figure) 将仅选择父元素,如果它是 figure 元素。
例如
/*
div.gallery
5*{
figure[tabindex=$]
img[src][alt]
figcaption
"caption"
}
*/
figure:focus:nth-parent(1):filter(.gallery) > figure:first-child {
样式...
}
该选择器将选择绝对时间顺序中的第一个同级元素(.gallery 中的第一个 figure)。
我喜欢这个想法。
我过去遇到过一些情况,我想为一般的链接设置悬停时的背景颜色,但如果我为包含图像的链接这样做,我会在使用图像的链接的填充区域看到带背景色的条形(行高很高)。能够选择包含图像的链接并以不同的方式设置它们的样式会非常方便。
大家好,
这个父选择器可能很有用,但它不会以某种方式违反 CSS 的本质吗?我的意思是,CSS 中的 c 代表“层叠”,选择器执行其选择以向下遍历 DOM 元素,而不是向后。这种类似鲑鱼的选择器非常有趣,我非常好奇它将如何发展!
抱歉,Paolo,但“层叠”指的是应用样式规则的顺序(从不太具体的规则到更具体的规则)——而不是 DOM 树中元素的排列顺序。
更准确地说,它指的是来自不同来源(例如,浏览器内置规则、作者和用户样式表规则、内联规则等)的规则在 DOM 中解析并应用于元素的顺序。参见:http://www.w3.org/TR/CSS2/cascade.html#cascade。
很棒的文章……但我个人从未使用过父标签……
有趣的是,有些人认为,既然他们没有遇到过自己需要它的实例,那么就不应该考虑它。如果 CSS 有一个支持的选项,为什么我们要从我们的技巧包中排除它,仅仅因为服务器端或客户端脚本可以实现解决方案呢?
今年我可能遇到过一两次这样的需求,并且只是承认这在未来几年可能不是一个选项。
我不是 CSS 专家,但“:contains”可能是这种功能的最佳候选者。如果它不是获取内容而是获取有效的 CSS 选择器,那么它就能解决问题。
@Paul Walker – 我非常喜欢你的想法,它比“:contains”简洁得多。但为了保持与 CSS 相同的模式,也许我们可以稍微修改一下,例如
div > a:$ > img —(或者任何其他代替 $ 的东西)。
可以从 jQuery 中获得灵感并使用
a:has(img) {
/* 如果 <img> 存在于其任何后代中,而不仅仅是作为直接子元素,则匹配 <a>。 */
}
a:has(> img) {
/* 如果 <img> 存在作为直接子元素,则匹配 <a>。 */
}
这就是
a img{}
的作用……
谢谢,非常有用
就像我现在使用的这个损坏的表单一样,“但是你可以用 jQuery 做样式”的所有论点完全违背了使用 CSS 进行展示和使用 Javascript 进行行为的目的。用 Javascript 设置样式?那为什么还要使用 CSS 呢?哎呀,我也可以用标记来设置我页面的样式……
*更多离题:同样,我发现上面这个表单中说明空空白表单字段目的的内容完全丢失了,直到我在浏览器中切换到 Javascript。嗯。需要行为来显示基本含义和内容?也许我们很久以前就放弃了关注点分离,而我错过了备忘录。
*回到主题:抛开性能问题不谈,对我来说,让声明性语言设置页面样式能够向上遍历 DOM 而不是只能向下遍历,这是很有道理的。再说一次,我很邪恶,也不介意一些正则表达式。还有圣诞节的玩具小马。
@Stomme – 我假设你在谈论 jQuery 和其他东西时指的是 @Jenna。她的意思是使用类似 jQuery 的语法在 CSS 中,而不是使用 jQuery 来设置页面样式。“:has”是 jQuery 中的一个伪选择器,所以她只是暗示我们可以在 CSS 中本地拥有类似的伪选择器。
@manu 不是她本人;有几个评论是关于“好吧,我可以在 jQuery 中做到这一点”(甚至只是 Javascript,如果你真的必须根据父元素确定样式,确实需要这样做…… :(
我看到多次提到 :has,也许他们都在说他们希望在 CSS 中有这种语法,而我误解了他们的意思,以为他们现在正在使用它来设置样式。
我确实宁愿不用脚本设置样式,但当它真的只能通过向上遍历 DOM 来完成时……CSS 就失败了。:(
优秀的文章,我们很少使用父标签,因为性能问题。LT
很酷的技巧……将在我的当前项目中使用它……谢谢
在我目前的工作中,我们正在选择一个新的 CMS 来替换我们自己开发的和老化的(8-9 年)CMS。我没有参与 CMS 的设计或架构,因为它是在我之前的时间,但是,我被迫使用它,直到我们有一个更好的解决方案。
问题是,在我们当前的解决方案中,有许多嵌套表,嵌套不正确的表,以及对在哪里或如何插入 ID 或 Class 以及插入到哪个元素的各种解释。
这个东西的输出很糟糕,尝试设置一个元素的样式可能会导致另一个元素出现问题。一个特例是我在一个页面中有多个 TD,没有主体 ID,并且一个主表 ID 与其他动态创建的页面共享。由于我可以将自己的选择器添加到最终 TD 内的元素中,因此我确实有能力针对这些选择器进行编码。
最近,我不得不做一些认真的忍术来设置一些治理页面的样式,唯一有意义的解决方案是使用某种形式的父选择。我求助于 Javascript 解决方案,它允许我随意定位父元素。这是一个非常丑陋的解决方案,但鉴于实际情况,这是必要的。
我使用的方法可以在这里找到:jQuery 动态 API 浏览器
导航到选择器 | 层次结构 | descendant(ancestor, descendant) 以查看示例。
基本上,语法如下
$(“#html_element_ID”).parent.css(“attribute”, “style”);
这会定位命名元素的特定父元素,并将所需的样式注入其中。这很混乱,也很麻烦,但是,有时你没有奢侈的时间在服务器端执行此操作或选择语义上合理的路径。
我认为父选择器可以为那些需要支持老化系统的人提供一些灵活性。在它存在之前,我们必须求助于上面这样的解决方案来进行补偿。
我的 0.02 美元
新的 Slick.js 选择器引擎支持反向组合器,包括 getParent 和 getDirectParent 组合器。它还支持许多其他组合器,如 getPreviousSiblings。
下载:http://mootools.net/core/826c8f047c6ae21b10342f3112de2cbf
GitHub:http://github.com/mootools/slick
Wiki:http://github.com/mootools/slick/wiki/Reversed-Combinators
我只能想到一个地方,父选择器会派上用场——仅仅是因为我刚刚发现了一个我无法用其他任何方法解决的问题(到目前为止)。我刚刚将我的网站切换到blogengine.net。我通过修改预设样式之一创建了我的网站样式。其中,有一个样式定义,用于向外部链接添加一个小图标。我总是忘记这一点,而且我喜欢它——所以我保留了它。
问题是,在我的某些帖子中,我有一些超链接图像指向外部地址。这些图像几乎总是浮动的。因此,我得到的是一个表示外部链接的无实体图标。例如,请参阅:http://www.mattlindley.info/post/2010/07/02/Hot-Damn!.aspx
如果我有一个父选择器,我就可以说“选择具有子元素(该子元素是图像)的外部链接”,并从这些元素中删除该图标。
照目前的情况,我只能使用一种不优雅的解决方案,即向那些特定的链接添加类似“rel”这样的属性,然后我可以指定删除图标。
这很棒,应该在CSS的新版本中实现。谢谢Chris
嗨.. Chris Coyier
我尝试了这段代码,但无法运行
样式
ul < li { padding-left:0px; }
html
请帮帮我..先谢谢了。
不起作用
@Arthur Lawry
非常聪明,将选定的元素放在最后..并坚持CSS的层叠规则,给你竖起大拇指。
无论如何,看到你的例子让我感到困惑。无意冒犯,但“IMG”元素怎么会有一个“A”元素作为子元素???
会是这样吗
[img src="foo.jpg" /] [a href="#"]mylink[/a] [ /img]
是不是很有趣?=D
另一种解决方案是将一些mutation observer javascript与css rel选择器结合起来,以提供“前瞻”。
因此,当DOM中的元素发生变化时,只需将该元素的选择器(带ID和类以及可能的事件,如悬停)记录到共享父元素的属性中。
因此,要选择一个具有类.clicked的曾孙元素,语法将如下所示
parent[contains*=”grandchild.clicked”] othergrandchild { … }
我在这里提供了一个示例
http://codepen.io/iautomation/pen/itJmz