Advertisement
Advertisement


Complex CSS selector for parent of active child


Question

Is there a way to select a parent element based on the class of a child element in the class? The example that is relevant to me relating to HTML output by a nice menu plugin for http://drupal.org. The output renders like this:

<ul class="menu">  
    <li>  
        <a class="active">Active Page</a>  
    </li>  
    <li>    
        <a>Some Other Page</a>  
    </li>  
</ul>  

My question is whether or not it is possible to apply a style to the list item that contains the anchor with the active class on it. Obviously, I'd prefer that the list item be marked as active, but I don't have control of the code that gets produced. I could perform this sort of thing using javascript (JQuery springs to mind), but I was wondering if there is a way to do this using CSS selectors.

Just to be clear, I want to apply a style to the list item, not the anchor.

2011/02/06
1
322
2/6/2011 9:08:29 PM

Accepted Answer

Unfortunately, there's no way to do that with CSS.

It's not very difficult with JavaScript though:

// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;

// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.
2012/08/21
151
8/21/2012 3:49:27 AM


Late to the party again but for what it's worth it is possible using jQuery to be a little more succinct. In my case I needed to find the <ul> parent tag for a <span> tag contained in the child <li>. jQuery has the :has selector so it's possible to identify a parent by the children it contains (updated per @Afrowave's comment ref: https://api.jquery.com/has-selector/):

$("ul").has("#someId")

will select the ul element that has a child element with id someId. Or to answer the original question, something like the following should do the trick (untested):

$("li").has(".active")
2017/09/26

THE “PARENT” SELECTOR

Right now, there is no option to select the parent of an element in CSS (not even CSS3). But with CSS4, the most important news in the current W3C draft is the support for the parent selector.

$ul li:hover{
    background: #fff;
}

Using the above, when hovering an list element, the whole unordered list will be highlighted by adding a white background to it.

Official documentation: https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview (last row).


The first draft of Selectors Level 4 outlines a way to explicitly set the subject of a selector. This would allow the OP to style the list element with the selector $li > a.active

From Determining the Subject of a Selector:

For example, the following selector represents a list item LI unique child of an ordered list OL:

OL > LI:only-child

However the following one represents an ordered list OL having a unique child, that child being a LI:

$OL > LI:only-child

The structures represented by these two selectors are the same, but the subjects of the selectors are not.

Edit: Given how "drafty" a draft spec can be, it's best to keep tabs on this by checking the CSSWG's page on selectors level 4.

2020/06/20

Future answer with CSS4 selectors

New CSS Specs contain an experimental :has pseudo selector that might be able to do this thing.

li:has(a:active) {
  /* ... */
}

The browser support on this is basically non-existent at this time, but it is in consideration on the official specs.


Answer in 2012 that was wrong in 2012 and is even more wrong in 2018

While it is true that CSS cannot ASCEND, it is incorrect that you cannot grab the parent element of another element. Let me reiterate:

Using your HTML example code, you are able to grab the li without specifying li

ul * a {
    property:value;
}

In this example, the ul is the parent of some element and that element is the parent of anchor. The downside of using this method is that if there is a ul with any child element that contains an anchor, it inherits the styles specified.

You may also use the child selector as well since you'll have to specify the parent element anyway.

ul>li a {
    property:value;
}

In this example, the anchor must be a descendant of an li that MUST be a child of ul, meaning it must be within the tree following the ul declaration. This is going to be a bit more specific and will only grab a list item that contains an anchor AND is a child of ul.

SO, to answer your question by code.

ul.menu > li a.active {
    property:value;
}

This should grab the ul with the class of menu, and the child list item that contains only an anchor with the class of active.

2018/12/12

I had the same problem with Drupal. Given the limitations of CSS, the way to get this working is to add the "active" class to the parent elements when the menu HTML is generated. There's a good discussion of this at http://drupal.org/node/219804, the upshot of which is that this functionality has been rolled in to version 6.x-2.x of the nicemenus module. As this is still in development, I've backported the patch to 6.x-1.3 at http://drupal.org/node/465738 so that I can continue to use the production-ready version of the module.

2009/05/18

Source: https://stackoverflow.com/questions/45004
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]