Grow your CSS skills. Land your dream job.

Parent Selectors in CSS

Published by Chris Coyier

Let's be clear here, just in case someone is finding this from a search engine: there are no parent selectors in CSS, not even in CSS3. It is an interesting topic to talk about though, and some fresh talk has surfaced.

Back in 2008, Shaun Inman suggested the syntax:

a < img { border: none; }

[Corrected the following sentence]: In this example, it would select a tags but only if they contained an img tag. (Aside: this would be a weird departure from the typical syntax where the actual elements being selected are on the right, this would be on the left).

Definitely read through the comments on that post, it is a super interesting thread, and contains some pretty signifiant reasons parent selectors don't exist yet. David Hyatt, a developer on the front-lines of implementing these kinds of things in WebKit, comments that:

With parent selectors it becomes extremely easy to accidentally cause a document-wide grovel. People can and will misuse this selector. Supporting it is giving people a whole lot of rope to hang themselves with.

Jonathan Snook resurfaced this topic and gives us lots of great background on how CSS rendering works. We've all heard before that the universal selector is the least efficient CSS selector. Jonathan says if there was a parent selector, that would then easily be the new top dog in inefficient selectors. The argument being that when elements are dynamically added and removed from the page, it may result in the entire document needing to be re-rendered (major memory usage concerns). Jonathan is still optimistic though:

What I've described is not technically impossible. In fact, quite the opposite. It just means that we'd have to deal with the performance implications of using such a feature.

Remy Sharp also gets in on the fun, and suggests this syntax:

a img:parent { background: none; }

The key difference being that the :parent syntax would only evaluate a single element, the parentNode available in the DOM for every element. This would be similar to forcing the :has selector to only evaluate children rather than all descendants.

So far everyone is in agreement:

  • There are huge performance concerns
  • Those concerns can be thought of as tradeoffs we should evaluate, not show-stoppers.
  • Want!

Comments

  1. Nice article, I personally don’t need parent selectors. And if it brings performance issues I think it’s not supposed to be in the spec.

    But hey, if you Chris CSS guru can come up with some scenario where parent selectors are making things so much easier. I would love to hear it.

    • I agree, I’d like to see a scenario where a parent selector would be vital, would make things easier or would be more efficient (if the performance issues would not exist).

    • Rick –

      Here’s one I ran into yesterday – I was styling a nav that is automatically generated from a CMS (so I have no way to add a class or id to the markup AND the order of the nav links might change over time, so I couldn’t use :nth selectors).

      I wanted the containing the URL http://foo.com to look a little different. It would have been awesome to be able to use something like li < a[href=http://foo.com] {background:red}

    • That’s indeed a nice example where the parent selector could be used. But do you want to style the ‘a’ or the ‘li’? Because if you want to style the ‘a’ you can just ignore the fact that it’s contained in a ‘li’ and do.

      a[href=http://foo.com]{//styling}

      Unless you only want it to style the ‘a’ in a specific place and not elsewhere on the site. Then you should restrict it with a requirement like:
      #header a[href=http://foo.com]{//styling}

    • Philippe Gilbert
      Permalink to comment#

      When styling hover, it would be nice to make the parent react when the child is selected.

    • Lou
      Permalink to comment#

      One good reason for parent selectors is when styling radio or checkboxes. Firefox for some reason doesn’t like backgrounds set on an input element like radio and checkboxes. I have a project where I use radio buttons that look like yes/no buttons (good for accessibility) and have a :checked on the input which puts a border around the button.

      However, that doesn’t work in FF. All I see is the actual radio button or checkbox. To style the input element, I would really need to put it inside a div tag and style that, but then the problem of getting the border around it when checked, hence; good cause for parent selector! :

      I’ve been seeing the “!” as a CSS4 draft so in my case it would be nice to do:

      Div! > input[type=radio]:checked { border: 2px solid #000; }

      The div would get the border when the input element is checked.

  2. Permalink to comment#

    Thanks for the tip, useful.

  3. Goran
    Permalink to comment#

    I don’t see real use of this.
    Aren’t a < img and a > img same thing

    • Ivan
      Permalink to comment#

      I guess Chris has made a typo of sort.

      With the proposed syntax would, “a < img" would select the "A"s who have an "IMG" descendant.

      A better way would be express it would be" "parent-selector that-has descendant-selector", where as you replace the "that-has" with "<".

    • The way Shaun described it is indeed the opposite of what I said, but I could see it working either way. I’d personally perfer it how I described it, meaning that the part of the selector furthest to the right would still be the actual element being selected, rather than the one furthest to the left.

    • Think of a multi-level dropdown menu. Some of the LI’s also contain another UL, but some do not. It would be cool to target only the one’s which are parent to another level, so you could, for example, apply an arrow indicator that this list item contains a sub menu. Right now there is no selector you can write to target a LI that contains a UL.

    • Phil
      Permalink to comment#

      You could just add a class to the parent LIs on the server side to achieve this.

    • You could. You could also have the server analyze how everything should look and just apply inline styling to each element as needed. Because there is some work around doesn’t mean CSS should remain neutered.

    • Permalink to comment#

      @Phil: Out of curiosity, how would you accomplish this? How do you give parent LI’s a class given they have a child UL using server-side methods? Doing this with jQuery is very simple, though I was not aware you can do this server side.

      Is there a “hasClass” PHP syntax?

    • Phil
      Permalink to comment#

      @Amit, No not in that sense, if you are outputting a menu for instance with multiple levels through running a loop or recursive function then you’ll know the top level LI has children and can add a class to it.

      @chris, I didn’t at any point suggest adding inline styles. Why and how would you analyze how anything should look on the server? I don’t see it as a work around, it’s a solution to the scenario you gave.

  4. Chris
    Permalink to comment#

    The a < img selector is actually stating “choose a if it has a child img”. Parent selectors would be quite helpful in a number of areas – e.g. div < input.error (that way you don’t have to repeat your error class definition up to a div or higher parent element if you want to show validation errors)

  5. garyh
    Permalink to comment#


    a < img { border: none; }
    In this example, it would select img tags but only if they were a child of an a tag.

    Rather than what you said, the (proposed) code above would select an a tag, but only if it was the parent of an img tag. What you suggested is already covered by:
    a img { ... }

    I think…

    • Cmet
      Permalink to comment#

      No, it’s not. Because (mostly (older) version of internet explorer) by default apply styling to the <a> element, namely a border for images and underline for text. You have to target the a-element.

      But suppose you want a nice dotted line under your ‘normal’ links, you can’t do that easily nowadays, but with parent selectors:

      a { border-bottom:1px dotted #eee; text-decoration:none; }
      a > img:parent { border-bottom:none; } 
  6. Permalink to comment#

    Great post Chris, thanks for the tip!

    • Remember that it’s not a “tip” really, this doesn’t exist yet, so don’t run off and try using it yet!

  7. Vasiliy Aksyonov
    Permalink to comment#

    It was in CSS3, but was removed: http://www.w3.org/TR/css3-selectors/#content-selectors
    (a:contains(img))

    • I’m not sure, but I think :contains whas a content selector in that it actually read the text in the node and selected based on that. So you could, for example, highlight a particular paragraph that contained a particular word…

  8. I think parent selectors would come in handy at certain times, but in most cases you should be able to use something a bit more efficient.

    I rarely use parent selectors with JavaScript (jQuery does a pretty good job in my opinion), but I try not to.

  9. I see where you are going with this Chris, and I like the idea. Now if only someone would spec it into CSS4 or something.

    I can see where a parent selector would be useful, as you could change, for example, the margins or colour of a h1 only if followed by a specific element.

    Maybe this can be put under a “CSS wish list” for future features – although there is the added complication of specificity if there are conflicting rules.

  10. Ricardo Verhaeg
    Permalink to comment#

    Well parent selector may come in hand but they need to support some pseudo classes too.
    Let’s say for example you have your menu in a way like: div > ul#menu > li*3 > a
    and you want that the div or li change the background on a:hover or a:focus with parent you could do something like:
    li < a:hover, li <a:focus {background:red;}
    today you do this by javascript or applying the hover to the li element.

    I do agree that we will have serious performance issues with that as said by Jonathan maybe the browsers could apply that with inner javascript so it won’t affect the performance but won’t exactly be a css parser.

    I really don’t mind not having it.. but as I said.. may come in hand..

  11. Permalink to comment#

    great
    it is better than using javascript getParent()

    could it be used more than once such as li:parent:parent ?

    • Cmet
      Permalink to comment#

      In my opinion, yes.
      Whether the syntax would be “li < ul", "ul < li", or "li:parent", I think it should always be possible to do it multiple times, in which case the "<" is more flexible.

      Ofcourse, in case you think the "<" syntax requires knowing the elemtent-tagname whereas the :parent does not, you're wrong. Because we could do "*" aswell:

      "* < tag", and "tag < *"

  12. Yes we are still probably missing interesting stuff like that as various possibilities have been proposed.

  13. Permalink to comment#

    Um yeah, in the rare cases you need this, just add a little bit of JS:
    E.g. http://pastie.org/849838

  14. Art Lawry
    Permalink to comment#

    It could just be personal preference, but I would think the following syntax makes more sense, especially for more complicated selectors:

    img < a

    instead of

    a < img

    Why? Because in every other css selector, it's the last element that describes what's getting styled. In this case, we want to style the a if it has a img child, so it makes more sense to put it on the end (again, personal preference I suppose).

    This could get really complicated when using deeper selectors but I like it. I remember wishing this existed on a recent project as well.

    • Art Lawry
      Permalink to comment#

      this potentially has the benefit of clarifying things like pseudoclasses

      a:hover < img seems to indicate the img style will change when the child a is hovered, moreso than img < a:hover

    • Cmet
      Permalink to comment#

      I agree “img < a" to select anchor-parents of of images makes more sense to me aswell.

  15. I’m not the first one telling this, but i think on the first example you meant “only if they were a parent of an a tag”… or not? you got me really confused for a while :)

  16. Permalink to comment#

    Mmm… my english is not so good, but I agree with Ivan : the example and the explanation don’t match with the topic of the article (you made a typo probably).
    I’m referring to


    a < img { border: none; }

    and

    “In this example, it would select img tags but only if they were a child of an a tag.”

    because also


    a img { border:none }

    select img tags only if they were a child of an a tag.

    instead a better example would be


    ul < li { padding-left:0px; }

    which removes the padding left to all the li tag which contain another ul level
    so in a multi level menu, all the items which have submenus.

  17. Steven
    Permalink to comment#

    ul li:hover a { background-color: #000000; }
    ul < li:hover { background-color: #cc0000; }

    Highlighting a child link on hover is okay, but highlighting the background of a unordered list should also be possible when interacting within a child element, such as an hover.

    We all remember when styling tables and input elements with CSS was limited … I'm sure there was good reason for shunning that too, but it didn't mean we needed to put up with it forever … so we didn't.

    Parent selectors are likely to be no different.

  18. Thera
    Permalink to comment#

    Good thing we have jQuery to be able to use the “:has” selector to simulate it, but it’s sad to have to either use the server-side or javascript for soemthing that would easy to have in real CSS.

    Just people are able to misuse something is no reason to invalidate that selector: people are more than very capable to misuse the existing ones already.

    • Thera
      Permalink to comment#

      Having to use the server-side script or javascript to simulate the parent selector feels the same as when you’re forced to use javascript to add a class to simulate the hover selector in IE6 :(

    • Thera
      Permalink to comment#

      Furthemore, there are already document-wide selectors already misused: how many websites use “*” for example ? And it has a much larger scope than a parent selector would.

    • Cmet
      Permalink to comment#

      Aside from :has, jQuery also has .parent(); Both have their good and bad times.

  19. Permalink to comment#

    “In this example, it would select img tags but only if they were a child of an a tag.”
    I think it would select a tags only if they were the parent of an img tag..

  20. Given experience I don’t think a designer should need a parent selector, in fact i think if it was introduced I would find it frustrating. Similar to reset style sheets I don’t use these, and I don’t need to because I understand how browsers work and compensate accordingly.

  21. Paul Walker
    Permalink to comment#

    What about tagging the element you wish to style within a statement with an exclamation mark?

    a > img selects images which descend from links
    a > img! would be the same.
    a! > img, however, would the links from which those images descend.

    I realised, after I’d thought about it, that this is *very* similar to the img will match all the same things as a > img, it’ll just style one level up from the match. Making this clear will make reading and writing these styles a lot simpler.

    Practically, by not being a selector on the same level as > or + or whatever, we make it possible to use the full scope of existing selectors for our qualifiers.

    In “qualified selectors” it isn’t altogether made clear what “<” does. Does div < img match the div in I think he says it would, but if it does, is it possible to qualify a selector with a statement that *doesn’t* begin with a descendant selector? If it doesn’t, how would one write a selector that would?

    Using . Even if it were doable, div img is simply awful.

    Exclamation marks are clearly different separate to the “relationship” selectors, , and they should attach themselves to “independent” selectors (class, ID, type, & pseudo selectors), to clarify their usage:

    blockquote! img
    blockquote! > img
    blockquote! + img
    div! > :checked

    • I like this one, I was thinking along the line of “circling” the selected element with parenthesis.

    • Arthur Lawry
      Permalink to comment#

      This is a great idea! Not sure what character is best to use, but this alleviates many of the concerns with the last element not representing the element to be styled, and also avoids the confusion with the reverse markup I mentioned earlier. I vote for $ rather than ! since the dollar sign resembles an S for “style this element”.

      div > a$ > img

  22. So few words and so much said. Great post, Chris.

  23. I’d love this concept if it wasn’t an issue with performance.

    So many times I want to style a link that contains just an image, and adding a class sucks.

    Would be wicked to use this for that instance, however, I feel the syntax would be

    img < a vs. a img, which is an image inside of an a, I want img < a, an a wrapping an image.

  24. I think it’s best to keep the selected element on the right, for consistency’s sake. img:parent(figure) would match all ancestor figure elements of the img. img:nth-parent(2) would select the grandparent of the img. img:parent would select all the ancestors. img:nth-parent(1):filter(figure) would select the parent only it it is a figure element.
    for example:

    /*
    div.gallery
    5*{
    figure[tabindex=$]
    img[src][alt]
    figcaption
    "caption"
    }
    */
    figure:focus:nth-parent(1):filter(.gallery) > figure:first-child {
    styleing...
    }

    that selector would select the first sibling in in absolute chronological order (the first figure in the .gallery)

  25. Permalink to comment#

    I like this idea.

    I’ve had cases in the past where I’ve wanted to style links in general with a background color on hover but if I do that for a link with an image I get background-coloured bars (line-height high presumably) showing in the padding area of links using images. Being able to select links containing images and style them differently would have been handy.

  26. Paolo
    Permalink to comment#

    Hi there guys,
    this parent selector could be useful, but wouldn’t it be somehow against the nature of css? I mean, the c in css stands for “cascading” and the selectors perform their selections descending DOM elements, not backwards. This salmon-like selector is very intriguing and I’m very curious on how it’ll evolve!

    • John Pisello
      Permalink to comment#

      Sorry, Paolo, but the “cascade” refers to the order in which the style rules are applied (from less to more specific rules)–not to the arrangement of elements in the DOM tree.

  27. John Pisello
    Permalink to comment#

    More precisely, it refers to the order in which rules from different sources (e.g., browser built-in rules, author- and user style sheet rules, inline rules, etc.) are resolved and applied to elements in the DOM. See: http://www.w3.org/TR/CSS2/cascade.html#cascade.

  28. Great article … but i personally never used parent tag…

  29. Permalink to comment#

    What’s interesting is that there are people out there who believe since they have not seen an instance where they themselves have needed it, then it shouldn’t be considered. If there’s a supported CSS option to something, why would we want to exclude that from our bag of tricks just because there’s a solution that can be achieved with server or client side scripting?

    I’ve probably come across this need at least once or twice this year and just conceded that it may not be an option for a few more years.

  30. Manu Goel
    Permalink to comment#

    I am no CSS expert but “:contains” could have been the best candidate for this kind of functionality. Only if instead of taking content it takes a valid CSS selector, it would solve the problem.

    @Paul Walker – I like your idea very much, it is much cleaner than “:contains”. But just to maintain the same pattern as CSS does, maybe we can modify it a little like this:

    div > a:$ > img — (or anything else in place of $ for that matter)

  31. Permalink to comment#

    Could take inspiration from jQuery and use:


    a:has(img) {
    /* matches an <a> if an <img> exists anywhere among its descendants, not just as a direct child. */
    }


    a:has(> img) {
    /* matches an <a> if an <img> exists as a direct child. */
    }

  32. Thank you, very useful indeed

  33. Stomme poes
    Permalink to comment#

    Just like this broken form I’m using now, all the arguments of “but you can do the stlyes with jQuery” so totally defeat the purpose of using CSS for presentation and Javascript for behaviour. Styling with Javascript? Then why use CSS at all? Heck I could go use markup to style my pages too…

    *more off-topic: Similarly, I found the content stating the purpose of the empty blank form fields in this form above was completely missing until I switched to Javascript-on browser. Hm. Behaviour required to show basic meaning and content? Maybe we abandoned the separation of concerns a while back and I missed the memo.

    *back on-topic: Performance issues aside, it makes plenty of sense to me to have the declarative language who styles the page be able to walk back up the DOM instead of only down. Then again, I’m evil and wouldn’t mind some regexen as well. And a p0ny for Christmas.

    • Permalink to comment#

      @Stomme – I assume you are referring to @Jenna when you talk about styling with jQuery and stuff. She meant using jQuery-like syntax in CSS, and not using jQuery to style pages. “:has” is a pseudo selector in jQuery, so she is just implying we can have a similar pseudo selector natively in CSS.

    • Stomme poes
      Permalink to comment#

      @manu not her specifically; there were several comments about “well I can just do that in jQuery” (or even just Javascript, which is indeed what one has to do IF you really must determine styles based on the parent… : (
      I saw several mentions of :has and maybe they were all saying they’d like that kind of syntax in CSS while I misread them to mean they were using that now for styling.

      I would indeed rather not have to use scripting for styling, but when it really can only be done by travelling back up the DOM… CSS fails. : (

  34. Excellent article, and we seldom use the parent tag because of performance. LT

  35. Permalink to comment#

    Cool tip… Will use it in my current project…. Thanx

  36. Permalink to comment#

    In my current job, we are in the process of selecting a new CMS to replace our home-grown and aging (8-9yrs) CMS. I had no hand in the design or architecture of the CMS, as it was before my time, however, I am forced to use it until we have a better solution.

    The issue is, in our current solution, there are many, many, many nested tables, incorrectly nested tables, and various interpretations of where or how an ID or Class should be inserted and to what element.

    The output of this thing is dreadful, and attempting to style one element can have the effect of breaking another. One particular case is where I have multiple TDs in a page with no body ID, and a main table ID which is shared with other dynamically created pages. Since I can add my own selectors to elements within the eventual TDs, I do have the ability to code against those selectors.

    Recently, I had to do some serious ninjitsu to style some of the governance pages, and the only solution that made sense, was to use some form of parent selection. I resorted to a JavaScript solution, which allowed me to target the parent elements at will. It was a totally ugly solution, but given the reality of the situation, it was necessary.

    The method I used can be found here: jQuery Dynamic API Browser

    Navigate to Selectors | Hierarchy | descendant(ancestor, descendant) to see an example.

    Basically, the syntax is as follows:

    $(“#html_element_ID”).parent.css(“attribute”, “style”);

    This targets the specific parent of​ the named element, and injects the desired style into it. It is messy, and a pain in the butt, however, sometimes you don’t have the luxury of doing it server-side or choosing a semantically sound path.

    I think parent selectors would allow for some flexibility for those who need to support aging systems. Until this exists, solutions like the one above are what we must resort to in order to compensate.

    My .02

  37. The new Slick.js selector engine supports Reversed Combinators, including both a getParent and getDirectParent combinator. It also supports many additional combinators like getPreviousSiblings.

    Download: http://mootools.net/core/826c8f047c6ae21b10342f3112de2cbf

    GitHub: http://github.com/mootools/slick

    Wiki: http://github.com/mootools/slick/wiki/Reversed-Combinators

  38. I can only think of one place where a parent selector would come in handy – and only because I just found a problem I cannot work out any other way (so far). I just switched my site to blogengine.net. I created my website style by modifying one of the preset styles. In that, there was a style definition to add a little icon to external hyperlinks. I always forget about that & I like it – so I have left it in.

    The problem is that I have, in some of my posts, hyperlinked images that point to an external address. These images are almost always floated. So, what I get is a disembodied icon indicating an external hyperlink. For example, see: http://www.mattlindley.info/post/2010/07/02/Hot-Damn!.aspx

    If I had a parent selector, I would be able to say “select external hyperlinks who have a child that is an image” and remove the icon from those elements.

    As it stands, I am left with an inelegant solution, which is to add something like a “rel” attribute to those particular links that I can then specify to remove the icons.

  39. Permalink to comment#

    its great and should be implemented in new version of CSS. Thank you Chris

  40. Mansukh
    Permalink to comment#

    Hi.. Chris Coyier

    i am try this code but can’t work it

    style
    ul < li { padding-left:0px; }

    html

    Test
    

    please help me ..thank’s in advanced.

  41. amit
    Permalink to comment#

    not workin

  42. Chef@thisisnotmyrealemail.com

    @Arthur Lawry

    img < a
    instead of
    a < img

    Very clever, putting the selected element at the last.. and stick with the CSS's cascading rule, a thumb's up for you.

    Anyway, seeing your examples made me confuse. No offense but, how come an "IMG" element has an "A" element as a child ???

    Will it be like this:
    [img src="foo.jpg" /] [a href="#"]mylink[/a] [ /img]
    Isn't that funny? =D

  43. Another solution is to combine a bit of mutation observer javascript with the css rel selector to provide a “lookahead”.

    So when an element changes in the dom, simply record that elements selector(with the id and classes and possible events, such as hover) into an attribute of the shared parent.
    So to select a child element with a great-cousin with the class .clicked , the syntax would look something like this:
    parent[contains*=”grandchild.clicked”] othergrandchild { … }

    I’ve provided an example here:

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".