149

I'm trying to apply styles to the parent if it has child elements.

So far, I've applied styles to the child elements if present. But I want to style the parent if the parent has child, using ONLY CSS.

following is the html

<ul class="main">
    <li>aaaa</li>
    <li>aaaa</li>
    <li>aaaa</li>
    <li>aaaa</li>
    <li>aaaa
        <ul class="sub">
            <li>bbbb</li>
            <li>bbbb
                <ul>
                    <li>cccc</li>
                    <li>cccc</li>
                    <li>cccc</li>
                </ul>
            </li>
            <li>bbbb</li>
            <li>bbbb</li>
            <li>bbbb</li>
        </ul>
    </li>
    <li>aaaa</li>
    <li>aaaa</li>
    <li>aaaa</li>
</ul>

the css code

* {
    margin:0;
    padding:0;
    text-decoration:none;
}
.main li {
    display:inline-block;
    background:yellow;
    color:green;
}
.main > li > ul > li {
    background:orange
}
.main > li > ul > li > ul >li {
    background:pink;
}

working FIDDLE

tanguy_k
  • 11,307
  • 6
  • 54
  • 58
Green Wizard
  • 3,507
  • 4
  • 18
  • 29
  • 5
    You can't. Bash the spec makers. – bjb568 Jan 21 '14 at 08:16
  • 2
    See http://stackoverflow.com/questions/45004/complex-css-selector-for-parent-of-active-child or http://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector – Jan Johansen Jan 21 '14 at 08:18
  • It's not possible, use the jquery. – Nikola Nikolić Jan 21 '14 at 08:18
  • 4
    Unfortunately I can only answer this question in a comment, but there is a CSS Selector for :empty so If you style the element for with children and then style for when no children with :empty you should achieve the effect you want. – user3094755 Feb 08 '16 at 17:56

1 Answers1

117

You can use has():

ul li:has(ul.sub) { ... }

It's not possible with CSS3. There is a proposed CSS4 selector, $, to do just that, which could look like this (Selecting the li element):

ul $li ul.sub { ... }

See the list of CSS4 Selectors here.

As an alternative, with jQuery, a one-liner you could make use of would be this:

$('ul li:has(ul.sub)').addClass('has_sub');

You could then go ahead and style the li.has_sub in your CSS.

Mikael Dúi Bolinder
  • 2,080
  • 2
  • 19
  • 44
MildlySerious
  • 8,750
  • 3
  • 28
  • 30
  • 20
    According to this similar question: http://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector the :has() pseudoclass no longer works with any browser as of 2016. Just so people don't get frustrated at this not working. – Ryan Smith Jun 28 '16 at 19:21
  • 1
    any developments ? – SuperUberDuper Jul 13 '16 at 12:22
  • 36
    :has() should be the proposed CSS4 selector instead of the more obscure $ one ... – Nicu Surdu Nov 29 '16 at 13:08
  • 5
    `$` now replaced with `!` appended to a selector. Look here for more info: https://www.w3.org/TR/selectors4/#subject – Dmitry Polushkin Mar 08 '17 at 14:17
  • 3
    @NicolaeSurdu you are right, w3 is so backwards – sites May 15 '17 at 22:13
  • 7
    According to the Feb 2018 working draft, `!` has been replaced with `:has()` – Mordred Aug 29 '18 at 03:13
  • As of 2/10/2022 :has is not supported by firefox or chrome. But MANY css4 selectors are! Using https://css4-selectors.com/browser-selector-test/ as a reference. – Jeff B Feb 10 '22 at 15:41
  • 2
    2022 :has() if finally implemented by Chrome (desktop) version 105, by Safari (both on mobile and desktop). I guess in about 6 months to 1 year we will finally have a stable :has() and solved this problem forever. – elano7 Jul 30 '22 at 13:43
  • 1
    today I tried to use the :has() pseudoClass and it worked as expected to apply style to a parent with a child having certain class. Chrome version used: 109.0.5414.120 MS Edge version used: 109.0.1518.70 – Sagar Feb 01 '23 at 06:25