[html] Apply CSS styles to an element depending on its child elements

Is it possible to define a CSS style for an element, that is only applied if the matching element contains a specific element (as the direct child item)?

I think this is best explained using an example.

Note: I'm trying to style the parent element, depending on what child elements it contains.

<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>

Note 2: I know I can achieve this using javascript, but I just wondered whether this is possible using some unknown (to me) CSS features.

This question is related to html css

The answer is


Basically, no. The following would be what you were after in theory:

div.a < div { border: solid 3px red; }

Unfortunately it doesn't exist.

There are a few write-ups along the lines of "why the hell not". A well fleshed out one by Shaun Inman is pretty good:

http://www.shauninman.com/archive/2008/05/05/css_qualified_selectors


In my case, I had to change the cell padding of an element that contained an input checkbox for a table that's being dynamically rendered with DataTables:

<td class="dt-center">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

After implementing the following line code within the initComplete function I was able to produce the correct padding, which fixed the rows from being displayed with an abnormally large height

 $('tbody td:has(input.a)').css('padding', '0px');

Now, you can see that the correct styles are being applied to the parent element:

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

Essentially, this answer is an extension of @KP's answer, but the more collaboration of implementing this the better. In summation, I hope this helps someone else because it works! Lastly, thank you so much @KP for leading me in the right direction!


On top of @kp's answer:

I'm dealing with this and in my case, I have to show a child element and correct the height of the parent object accordingly (auto-sizing is not working in a bootstrap header for some reason I don't have time to debug).

But instead of using javascript to modify the parent, I think I'll dynamically add a CSS class to the parent and CSS-selectively show the children accordingly. This will maintain the decisions in the logic and not based on a CSS state.

tl;dr; apply the a and b styles to the parent <div>, not the child (of course, not everyone will be able to do this. i.e. Angular components making decisions of their own).

<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>