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


Translate

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.


All Answers
  • Translate

    As far as I'm aware, styling a parent element based on the child element is not an available feature of CSS. You'll likely need scripting for this.

    It'd be wonderful if you could do something like div[div.a] or div:containing[div.a] as you said, but this isn't possible.

    You may want to consider looking at jQuery. Its selectors work very well with 'containing' types. You can select the div, based on its child contents and then apply a CSS class to the parent all in one line.

    If you use jQuery, something along the lines of this would may work (untested but the theory is there):

    $('div:has(div.a)').css('border', '1px solid red');
    

    or

    $('div:has(div.a)').addClass('redBorder');
    

    combined with a CSS class:

    .redBorder
    {
        border: 1px solid red;
    }
    

    Here's the documentation for the jQuery "has" selector.


  • Translate

    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


  • Translate

    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>