根据子元素的情况为一个元素应用CSS样式

257

如果匹配的元素包含特定元素(作为直接子项),是否可以定义一个仅适用于该元素的CSS样式?

我认为可以通过示例来最好地解释这一点。

注意:我正在尝试根据父元素所包含的子元素来设置父元素的样式

<style>
  /* note this is invalid syntax. I'm using the non-existing
   ":containing" pseudo-class to show what I want to achieve. */
  div:containing div.a { border: solid 3px red; }
  div:containing div.b { border: solid 3px blue; }
</style>

<!-- the following div should have a red border because
     if contains a div with class="a" -->
<div>
  <div class="a"></div>
</div>

<!-- the following div should have a blue border -->
<div>
  <div class="b"></div>
</div>

注意 2: 我知道我可以使用JavaScript来实现这个功能,但我只是想知道是否有一些我不知道的CSS特性可以实现。


1
你可能想要更新问题的陈述,或许使用闪烁的粗体文本,表明你正在尝试为父级div设置样式,而不是其子元素。我知道这个信息已经在问题本身中了,但除非你想得到大量错误的答案,否则这可能值得一试。 - Seth Petry-Johnson
谢谢@Seth。我尝试改进了问题的标题和内容。如果您认为仍然不清楚,请编辑问题。 - M4N
这是CSS中为什么支持这种类型的理想示例:ol < li:nth-child(n+10) { margin-left: 2rem; } ol < li:nth-child(n+100) { margin-left: 3rem; } ol < li:nth-child(n+1000) { margin-left: 4rem; } 在理想的情况下,这将根据包含的li子元素数量增加ol的边距,以便左侧的边距只有必要时才会变宽。 - Jonmark Weber
实际上,这个功能正在使用 :has 选择器进行开发 - https://bkardell.com/blog/canihas.html - Giedrius
4个回答

175

该语法为:

div:has(div.a) { border: solid 3px red; }
div:has(div.b) { border: solid 3px blue; }

据我所知,CSS没有提供基于子元素样式化父元素的功能。您可能需要脚本来实现这一点。

如果您可以使用诸如 div[div.a]div:containing[div.a] 这样的内容,那将是非常好的,但这是不可能的。

您可以考虑使用 jQuery。它的选择器可以很好地与“包含”类型配合使用。您可以选择 div 元素,根据其子元素内容应用 CSS 类,并且这些操作可以在一行中完成。

如果您使用 jQuery,以下代码可能会起作用(未经测试,但理论上有效):

$('div:has(div.a)').css('border', '1px solid red');
或者
$('div:has(div.a)').addClass('redBorder');
与 CSS 类结合使用:
.redBorder
{
    border: 1px solid red;
}

这里是jQuery的“has”选择器的文档。


15
注:为了提高性能,jQuery文档页面针对:has选择器建议使用.has()方法(http://api.jquery.com/has/)=> 应用于当前问题,例如$('div').has('div.a').css('border', '1px solid red'); - Maxime Pacary
为了使其工作,必须使用变异观察器来检查子元素是否更改了其状态... - Legends
2
这并不是真正回答问题的方法,问题是“有没有办法用CSS来实现这个”。明确地说明:“我知道可以使用JavaScript实现这一点,但我只是想知道是否有可能使用一些未知(对我来说)的CSS特性来实现。” - SunshinyDoyle
3
https://developer.mozilla.org/zh-CN/docs/Web/CSS/:has,我认为这个 :has 选择器可以工作,但它仍处于草案版本,没有浏览器支持它。 - AliF50
3
截至2022年10月,它在Chrome和Edge上得到支持,但除非用户修改about:config,否则在Firefox上不受支持。 - user7868

81

69
8年后的最新消息是:该选择器方法仍然没有得到支持。 - Kraang Prime
2
这个功能的工作草案以 :has() 伪类的形式存在,但我们只能在 CSS4 中使用它。截至目前(2019年末),JavaScript 仍然是实现此功能的唯一途径。 - zepp133
我认为这不会启用CSS样式,仍然需要JavaScript来使用选择器。除非这已经改变了? - Justin Wignall
8
9年过去了,他们认为这个功能是不必要的吗? - Loi Nguyen Huynh
5
11年过去了,我和许多人仍在寻找解决方案! - Masoud Tahmasebi
显示剩余2条评论

1

除了 @kp 的回答之外:

我正在处理这个问题,在我的情况下,我必须显示一个子元素并相应地调整父对象的高度(自动大小调整在引导页眉中由于某种原因不起作用,我没有时间进行调试)。

但是,我认为我将动态向父级添加CSS类,并根据CSS选择性地显示子级,而不是使用JavaScript修改父级。这将保持逻辑中的决策,而不是基于CSS状态。

tl;dr;ab 样式应用于父级 <div>,而不是子级(当然,并非每个人都能够做到这一点。例如,Angular 组件会自行做出决策)。

<style>
  .parent            { height: 50px; }
  .parent div        { display: none; }
  .with-children     { height: 100px; }
  .with-children div { display: block; }
</style>

<div class="parent">
  <div>child</div>
</div>

<script>
  // to show the children
  $('.parent').addClass('with-children');
</script>

0
在我的情况下,我必须更改包含动态渲染的DataTables表中的输入复选框的元素的单元格填充。
<td class="dt-center">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

initComplete函数中实现以下代码行后,我能够产生正确的填充,从而修复了显示具有异常大高度的行的问题。
 $('tbody td:has(input.a)').css('padding', '0px');

现在,您可以看到正确的样式已应用于父元素:

<td class=" dt-center" style="padding: 0px;">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

本质上,这个答案是@KP答案的延伸,但是实现的更多协作越好。总之,我希望这能帮助到其他人,因为它是有效的!最后,非常感谢@KP引导我走向正确的方向!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接