CSS 中存在“父选择器”是人们经常提到的 CSS 非常需要的东西。 我感觉自己也无数次想过这个想法,但当我让大脑想一个用例时,却很难想到。 好吧,我刚想到一个,所以我想在这里记录一下。
经典的父/子关系
<div class="parent">
<div class="child"></div>
</div>
假设让这个父级元素拥有隐藏溢出,同时让子级使用绝对定位是有道理的。
.parent {
overflow: hidden;
position: relative;
}
.child {
position: absolute;
}
现在假设有一个特殊情况,需要将子级定位在父级元素之外,并且仍然可见。 隐藏溢出仍然是大多数情况下的良好默认值,因此最好保留此规则,但在这种非常特殊的情况下,我们需要覆盖该溢出。
.special-child {
position: absolute;
bottom: -20px; /* needs to be slightly outside parent */
}
/* Not real, but just to make a point */
.special-child:parent(.parent) {
overflow: visible;
}
上面的选择器是假的,但它的意思是“选择 .special-child
的父级元素”,这将允许根据需要进行覆盖。 也许就像这样
.parent < .special-child {
}
… 这样会选择左侧的元素而不是右侧的元素。 谁知道呢? 也许这两个都存在问题,最终的语法会是别的。 也许我们永远不会得到它。 我不知道。 只是记录一下我遇到的一个真实的用例。
你可能会想,“为什么不直接在父级元素上使用另一个特殊类?” 我本来会这么做的,但是这个父级元素是通过一个不提供在我选择的父级元素上添加类的 API 由第三方库注入的。 最终,我不得不通过编写一些自定义 JavaScript 来添加该类到父级元素,该 JavaScript 查询 DOM 以查找 .special-child
,找到父级元素,然后在其中添加该类。
你们有没有其他父选择器的用例?
来自 Uzair Hayat 的一个
我的项目中有一个
<input>
,它被包装在一个<div>
中。<div>
具有一些设计元素,这些元素需要在<input>
处于:focus
状态时生效。 我可以使用::before
和::after
伪元素,但输入元素不支持它们,因为它们是替换元素。 现在,我使用 JavaScript 来检测输入元素是否处于焦点状态,并在父级 div 上应用一个类。 我希望我能这样做……
input:focus:parent(div):after {
display: block;
/* display design changes when focused */
}
CSS 应该支持 XPath!
我今天遇到了一个,一组单选按钮代码如下
<label>一个选择 <input type="radio"></label>
当用户完成他们的单选按钮选择并提交他们的回复时,我将输入设置为禁用
<label>一个选择 <input type="radio" disabled="disabled"></label>
能够根据
disabled
属性的存在来设置<label>
的样式会非常方便。这是一个很好的例子,说明了父选择器有多方便。 但是,您可以通过将输入元素从标签中取出以完成此任务。
你可能已经考虑过这个
`
input[disabled] ~ label {
color: #777;
}
字段名称
`
可能可以使用大多数 CSS 来做你想做的事,方法是使用一个隐藏的复选框,并结合 HTML 的
id
和for
标签重定向。HTML 看起来可能有点像…
… 然后设置样式,使复选框状态通过
~
影响标签…… 为了完整性,添加一些 JavaScript 来切换单选按钮的状态…
关于 StackOverflow 上的 CSS 父选择器 的答案可能值得一读,以了解复选框和标签可以做到的其他事情。
标签和输入元素不能是兄弟元素吗?
:has()
伪类怎么样?https://mdn.org.cn/en-US/docs/Web/CSS/:has
.parent:has(> .special-child) {}
选择具有一个名为 sepcial-child 的直接子元素的父级类。
我受过教育的猜测是我们会看到类似于
.parent:has-child(.special-child)
的语法。@Joe Maffei
它们可以是兄弟元素,但这样就会失去该元素添加的语义,因为这样就会导致通过单击标签来选择单选按钮,这是故意的,也是使用标签元素而不是任何其他元素的原因。
这可能很像你的用例,但父选择器的另一个用例是特定组件的容器,该容器位于没有类自身的元素列表中,可能是因为你无法直接访问底层源代码。 例如,主页面代码可能如下
父选择器在那里比通过 JavaScript 添加类或使用 div:nth-of-type(3) 方便得多。
而且它也更不容易出错。 如果他们后来改变了顺序,使得日历现在是页面上的第二个块,你原来的 CSS 就会失效。 所以如果你选择了前者,你每次改变页面顺序都需要更新它。
所以这是一个用例。 尽管如此,我知道人们会质疑它。 毕竟,你不能直接修改底层代码在父级元素上添加一个类吗?
不一定。 如果你运行了相关的网站并拥有服务器访问权限,你可以这样做,但有时你使用第三方工具(比如 VWO 或 Target)对客户网站进行 A/B 测试。 这些工具除了通过 JavaScript 或 CSS 可以编辑的内容外,不会给你任何对页面源代码的访问权限。
此外,它们通常也是以“通用”为目标,比如“对 URL 以 blog 开头的所有页面运行此测试”。 因此,仅使用 CSS 来定位这些元素是一件很麻烦的事情。
所以,我认为 A/B 测试是父选择器的另一个很好的用例,尤其是在对没有足够的类名来识别特定元素的网站(除了使用 “nth-of-type/nth-child” 的技巧)进行测试时。
我们指的是直接父选择器,还是更通用(但在性能方面可能成本更高)的祖先选择器?
后者用例可能是防止模态窗口打开时出现 body 滚动
考虑到
dialog
元素最好放在body
标签的直接子元素中,我想上面也可以用“仅仅”一个直接父选择器来实现,但这无关紧要。我非常希望这样的选择器能尽快实现。 从我的经验来看,它比
:is
有更多的用例。事实上,工作草案已经包含了 关系型伪类
:has()
,它可以实现这个目的。使用
:has()
,用例选择器可以写成.parent:has(> .special-child)
。目前,MDN 指出,此伪选择器不能在样式表中使用,只能在像
document.querySelector('div:has(h1)')
这样的 JS 函数中使用。 我认为这与页面中实时计算父选择器的复杂性有关。我想要 CSS 父选择器的绝大多数时间是为了设置无法轻松直接编辑的 HTML 的样式(例如,某些 WordPress 插件的输出)。 我偶尔会使用 Javascript 来添加我自己的 HTML,只是为了得到一些可以设置样式的目标,而 CSS 父选择器本来可以做到这一点!
它会达到一个点,CSS 会让我们要求它做的事情越多,它就越会失效。 从几年前我读到的内容来看,父选择器对 CSS 的工作方式是有害的…… 因为级联。 不仅从样式表角度来看,而且从设计和文档流角度来看也是如此。
我觉得如果我们太努力地推动这个,我们会让 CSS 变成丑陋而优雅的东西。
每种语言都会有 总是 有 总是 限制。 我认为我们应该保持现状。
我只在刚开始做 CSS 设计师的时候 需要 父选择器。 尝试通过评估你的流程和结构来绕过这个限制。(你必须这样做,因为没有父选择器)并接受,如果这是 CSS 中最糟糕的限制,那么它并没有那么糟糕。
我经常发现自己希望 CSS 有一个父选择器。 与你描述的类似,我使用的软件有许多元素被分配了动态 ID,这些 ID 无法依赖。 我经常需要设置某个元素父级的样式,但我没有一个简单的方法来引用它。 我被迫要么从某个有稳定 ID 的曾曾曾曾曾祖父级开始引用它,要么找到一个巧妙的伪选择器用法。
我使用 RPA 产品,这些产品使用 CSS 选择器来查找要提取和交互的元素。在一个具有动态 ID 的网站上,父选择器会非常有用,因为元素只能通过其文本(标题和表格列)来定位。
但我认为这些工具应该提供父级选择,而不是选择器本身。
编辑之前的评论,如果已经知道父元素是什么,则不需要类选择器。
div:has(> .child) 会返回父 div。
仔细想想,我们真正需要的不是父选择器,而是父组合器。像假设的 :parent 这样的伪类选择器会像对匹配选择器之前部分的标签列表的过滤器一样工作,因此 li:parent 会获取所有 <li> 标签并对其进行过滤,并返回匹配的 <li>,但在这种情况下,这不是我们想要的—我们可能希望选择包含它的 <ul>。
我已经问过 CSSWG CSS 作者可以使用什么语法来表示自定义选择器组合器(如果你要自己 DIY 支持这个功能),他们告诉我使用一对斜杠,包围以双破折号开头的自定义 IDENT,比如 /--custom-combinator/。任何希望在有效 CSS 语法中支持他们自己的自定义父组合器的人应该支持类似 /--parent/ 这样的东西,或者任何对你有意义的名称,这样你就可以编写像 li /--parent/ ul {} 这样的选择器,它会定位每个匹配 <li> 标签的 <ul> 父级。
只是为了好玩—我们已经在工作中的 CSS 中使用 /--parent/ 语法支持自定义父组合器,请在这里查看它,并使用 process-css-demo 自己玩一下:https://twitter.com/innovati/status/1207710819242463234
我今天遇到了一个,就想到了这篇文章。
一个带有 .is-visible 类的模态窗口,可以选择 body 元素并将 overflow 设置为“hidden”,以防止背景滚动。