By jcuenod

2009-06-18 19:59:36 8 Comments

How do I select the <li> element that is a direct parent of the anchor element?

As an example, my CSS would be something like this:

li < {
    property: value;

Obviously there are ways of doing this with JavaScript, but I'm hoping that there is some sort of workaround that exists native to CSS Level 2.

The menu that I am trying to style is being spewed out by a CMS, so I can't move the active element to the <li> element... (unless I theme the menu creation module which I'd rather not do).

Any ideas?


@Dmitry Sokolov 2020-01-31 15:53:33

There no css (and therefore in css preprocessors) parent selector due to "The major reasons for the CSS Working Group previously rejecting proposals for parent selectors are related to browser performance and incremental rendering issues."

@Damiano 2019-06-13 08:25:27

I'd hire some JavaScript code to do that. For example, in React when you iterate over an array, add another class to the parent component, which indicates it contains your children:

<div className={`parent ${hasKiddos ? 'has-kiddos' : ''}`}>
    { => <div key={} />)}

And then simply:

.parent {
    color: #000;

.parent.has-kiddos {
    color: red;

@Jan Kyu Peblik 2018-07-31 22:47:03

Here's a hack using pointer-events with hover:

<!doctype html>
/* accessory */
.parent {
	width: 200px;
	height: 200px;
	background: gray;
.selector {
	display: flex;
	justify-content: center;
	align-items: center;
.selector {
	cursor: pointer;
	background: silver;
	width: 50%;
	height: 50%;
/* pertinent */
.parent {
	background: gray;
	pointer-events: none;
.parent:hover {
	background: fuchsia;
.selector {
	pointer-events: auto;
		<div class="parent">
			<div class="selector"></div>

@John 2019-06-21 10:57:46


While technically not a parent selector it will allow you to select the page URL which is about as "parent" as it gets. Please keep in mind you will need to advocate for this (see the bottom of this post for further instructions). I'll update this post once this method becomes viable by web authors.

Let us say you want to change the background-image of the navigational header for each page. Your HTML would generally look like the following:


<main id="about_"></main>



Adding an id attribute to the head and body elements isn't professional and non-compliant with Web 3.0. However by selecting the URL you don't have to add any HTML code in any sense:

@document url('')
 body > header
  background-image: url(about.png);

Because you are a professional (you are, aren't you?) you always test your code local before deploying it to the live server. So static URLs aren't going to work on localhost,, :1 and so forth - by default. That implies that if you're going to successfully test and verify your code that you're going to need to run server-side scripting on your CSS. That also implies that if you allow users to run CSS on your site that you should ensure their CSS code can't run server-side scripting though yours can. Most people who would find this part of the post useful may not be sure how to approach it and it all comes down to how you organize your work environment.

  1. Always run your local environment on RAID 1, 5, 6, 1+0 or 0+1 (commonly mistaken as the non-existent "RAID 10" and 0+1 and 1+0 are very different beasts).
  2. Do not store your work (and personal files) on the same drive as your OS; you will be reformatting eventually whether you're in the mood to or not.
  3. Your root path should look something like this (on a WAMP (Windows, Apache, MariaDB and PHP) server): D:\Web\Version 3.2\\.
  4. In PHP you will start with your $_SERVER['DOCUMENT_ROOT'] (you can determine a Linux OS via if (substr($_SERVER['DOCUMENT_ROOT'],0,1) == '/') {} condition).
  5. You keep copies of older versions because you need to see working copies in case you forgot and screwed something up, hence the versioning.

The following presumes that your live server uses www. ( instead of

if (!isset($_SERVER['HTTP_HOST']))
//Client does not know what domain they are requesting, return HTTP 400.
 //Get the domain name.
 if (substr($_SERVER['HTTP_HOST'],0,4) === 'www.')
 {//Live Server
  $p0 = explode('www.',$_SERVER['HTTP_HOST'],2);
  $domain = $p0[1];
  $p0 = explode('www.',$_SERVER['REQUEST_URI']);

  if (isset($p0[2]))
   $p1 = explode('/',$p0[2],2);
   $domain = $p1[0];
   $p1 = explode('/',$p0[1],2);
   $domain = $p1[0];

 //Now reconstruct your *relative* URL.
 if (isset($_SERVER['HTTPS'])) {$https = 'https';}
 else {$https = 'http';}

 $p0 = explode('www.',$_SERVER['HTTP_HOST']);

 if (stristr($_SERVER['HTTP_HOST'],'www.'))
  $a = array('p1'=>$https.'://www.'.$domain, 'p2'=>'/');
  $dir_ver = explode('/www.',$_SERVER['REQUEST_URI']);

  if ($_SERVER['HTTP_HOST']=='localhost' || $_SERVER['HTTP_HOST']==$_SERVER['SERVER_NAME'])
   $p0 = explode($domain,$_SERVER['REQUEST_URI']);
   $a = array('p1'=>$https.'://'.$_SERVER['HTTP_HOST'], 'p2'=>htmlspecialchars($p0[0].$domain).'/');
  else if (substr($_SERVER['HTTP_HOST'],0,7)=='192.168' || substr($_SERVER['HTTP_HOST'],0,4)=='127.')
   $p0 = explode($domain,$_SERVER['REQUEST_URI']);
   $a = array('p1'=>$https.'://'.$_SERVER['HTTP_HOST'], 'p2'=>htmlspecialchars($p0[0].$domain).'/');


The $a will return two parts of your URL. Your front page or website's root URL will be the / so about/ would be about/ once you explode or split when comparing strings. That will get you about 80% of the way (for both local and live testing) so you can run the same code in both environments and use it in the CSS to reconstruct the URLs.

Browser Support

As of 2019 only Gecko 61+ supports this feature and only behind a flag. I have already advocated that it becomes usable by web authors. David Baron is the author of CSS Conditional Rules Module Level 3. The primary reasoning that an actual CSS "parent selector" does not exist is because of the performance impact; this method would negate the performance impact. I also advocated that relative URLs should be supported in the presence of the HTML base element. If you are reading this in or not long after the year 2019 (hello to everyone in the year 47,632!) please first reference the following URLs:

@S0AndS0 2019-06-08 06:31:18

Any ideas?

CSS 4 will be fancy if it adds some hooks into walking backwards. Till then it is possible (though not advisable) to use checkbox and/or radio inputs to break the usual way that things are connected, and through that also allow CSS to operate outside of its normal scope...

/* Hide things that may be latter shown */
.menu__hidden {
  display: none;
  visibility: hidden;
  opacity: 0;
  filter: alpha(opacity=0); /* Old Microsoft opacity */

/* Base style for content and style menu */
.main__content {
  background-color: lightgray;
  color: black;

.menu__hidden {
  background-color: black;
  color: lightgray;
  /* Make list look not so _listy_ */
  list-style: none;
  padding-left: 5px;

.menu__option {
  box-sizing: content-box;
  display: block;
  position: static;
  z-index: auto;

/* &#9660; - \u2630 - Three Bars */
.menu__trigger__selection::before {
  content: '\2630';
  display: inline-block;

/* &#9660; - Down Arrow */
.menu__trigger__selection::after {
  content: "\25BC";
  display: inline-block;
  transform: rotate(90deg);

/* Customize to look more `select` like if you like */
.menu__trigger__style:active {
  cursor: pointer;
  background-color: darkgray;
  color: white;

 * Things to do when checkboxes/radios are checked

.menu__checkbox__selection:checked + .menu__trigger__selection::after,
.menu__checkbox__selection[checked] + .menu__trigger__selection::after {
  transform: rotate(0deg);

/* This bit is something that you may see elsewhere */
.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
  display: block;
  visibility: visible;
  opacity: 1;
  filter: alpha(opacity=100); /* Microsoft!? */

 * Hacky CSS only changes based off non-inline checkboxes
 * ... AKA the stuff you cannot unsee after this...
.menu__checkbox__style[id="style-default"]:checked ~ .main__content {
  background-color: lightgray;
  color: black;

.menu__checkbox__style[id="style-default"]:checked ~ .main__content .menu__trigger__style[for="style-default"] {
  color: darkorange;

.menu__checkbox__style[id="style-one"]:checked ~ .main__content {
  background-color: black;
  color: lightgray;

.menu__checkbox__style[id="style-one"]:checked ~ .main__content .menu__trigger__style[for="style-one"] {
  color: darkorange;

.menu__checkbox__style[id="style-two"]:checked ~ .main__content {
  background-color: darkgreen;
  color: red;

.menu__checkbox__style[id="style-two"]:checked ~ .main__content .menu__trigger__style[for="style-two"] {
  color: darkorange;
  This bit works, but will one day cause troubles,
  but truth is you can stick checkbox/radio inputs
  just about anywhere and then call them by id with
  a `for` label. Keep scrolling to see what I mean
<input type="radio"
<input type="radio"
<input type="radio"

<div class="main__content">

  <p class="paragraph__split">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

  <input type="checkbox"
  <label for="trigger-style-menu"
         class="menu__trigger__selection"> Theme</label>

  <ul class="menu__hidden">
    <li class="menu__option">
      <label for="style-default"
             class="menu__trigger__style">Default Style</label>

    <li class="menu__option">
      <label for="style-one"
             class="menu__trigger__style">First Alternative Style</label>

    <li class="menu__option">
      <label for="style-two"
             class="menu__trigger__style">Second Alternative Style</label>

  <p class="paragraph__split">
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


... pretty gross, but with just CSS and HTML it is possible to touch and re-touch anything but the body and :root from just about anywhere by linking the id and for properties of radio/checkbox inputs and label triggers; likely someone'll show how to re-touch those at some point.

One additional caveat is that only one input of a specific id maybe used, first checkbox/radio wins a toggled state in other words... But multiple labels can all point to the same input, though that would make both the HTML and CSS look even grosser.

... I'm hoping that there is some sort of workaround that exists native to CSS Level 2...

I am not sure about the other : selectors, but I :checked for pre-CSS 3. If I remember correctly, it was something like [checked] which is why you may find it in the above code, for example,

.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
 /* rules: and-stuff; */

... but for things like ::after and :hover, I'm not at all certain in which CSS version those first appeared.

That all stated, please don't ever use this in production, not even in anger. As a joke sure, or in other words just because something can be done does not always mean it should.

@roberrrt-s 2019-03-19 14:14:57

It's now 2019, and the latest draft of the CSS Nesting Module actually has something like this. Introducing @nest at-rules.

3.2. The Nesting At-Rule: @nest

While direct nesting looks nice, it is somewhat fragile. Some valid nesting selectors, like .foo &, are disallowed, and editing the selector in certain ways can make the rule invalid unexpectedly. As well, some people find the nesting challenging to distinguish visually from the surrounding declarations.

To aid in all these issues, this specification defines the @nest rule, which imposes fewer restrictions on how to validly nest style rules. Its syntax is:

@nest = @nest <selector> { <declaration-list> }

The @nest rule functions identically to a style rule: it starts with a selector, and contains declarations that apply to the elements the selector matches. The only difference is that the selector used in a @nest rule must be nest-containing, which means it contains a nesting selector in it somewhere. A list of selectors is nest-containing if all of its individual complex selectors are nest-containing.

(Copy and pasted from the URL above).

Example of valid selectors under this specification:

.foo {
  color: red;
  @nest & > .bar {
    color: blue;
/* Equivalent to:
   .foo { color: red; }
   .foo > .bar { color: blue; }

.foo {
  color: red;
  @nest .parent & {
    color: blue;
/* Equivalent to:
   .foo { color: red; }
   .parent .foo { color: blue; }

.foo {
  color: red;
  @nest :not(&) {
    color: blue;
/* Equivalent to:
   .foo { color: red; }
   :not(.foo) { color: blue; }

@Eduard Florinescu 2018-02-01 14:18:25

At least up to and including CSS 3 you cannot select like that. But it can be done pretty easily nowadays in JavaScript, you just need to add a bit of vanilla JavaScript, notice that the code is pretty short.

cells = document.querySelectorAll('div');
[], function (el) {
    if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
<div><a href="#">Jackson link</a></div>
<div><a href="#">Pullman link</a></div>

@Yukulélé 2018-01-20 20:22:01

Yes: :has()

Browser support: none

@Rodolfo Jorge Nemer Nogueira 2017-08-03 18:19:03

It's possible with ampersand in Sass:

  font-size: 20px
  margin-bottom: 10px
  .some-parent-selector &
    font-size: 24px
    margin-bottom: 20px

CSS output:

h3 {
  font-size: 20px;
  margin-bottom: 10px;
.some-parent-selector h3 {
  font-size: 24px;
  margin-bottom: 20px;

@Shahar 2017-08-09 08:02:11

it's true, but only if you know the selector in advance.

@Jacob Ford 2019-03-25 12:41:09

This does not select h3's parent, which was the goal. This would select h3s which are descendants of .some-parent-selector.

@Alireza 2017-06-16 18:06:57

The short answer is NO; we don't have a parent selector at this stage in CSS, but if you don't have to swap the elements or classes anyway, the second option is using JavaScript. Something like this:

var activeATag ='')); {
  if(x.parentNode.tagName === 'LI') { = 'red'; // Your property: value;

Or a shorter way if you use jQuery in your application:

$('').parents('li').css('color', 'red'); // Your property: value;

@innovati 2016-04-07 17:52:31

There's a plugin that extends CSS to include some non-standard features that can really help when designing websites. It's called EQCSS.

One of the things EQCSS adds is a parent selector. It works in all browsers, Internet Explorer 8 and up. Here's the format:

@element '' {
  $parent {
    background: red;

So here we've opened an element query on every element, and for the styles inside that query, things like $parent make sense, because there's a reference point. The browser can find the parent, because it's very similar to parentNode in JavaScript.

Here's a demo of $parent and another $parent demo that works in Internet Explorer 8, as well as a screenshot in case you don't have Internet Explorer 8 around to test with.

EQCSS also includes meta-selectors: $prev for the element before a selected element and $this for only those elements that match an element query, and more.

@Gaurav Aggarwal 2015-11-27 21:16:35

No, you cannot select the parent in CSS only.

But as you already seem to have an .active class, it would be easier to move that class to the li (instead of the a). That way you can access both the li and the a via CSS only.

@Ilya B. 2015-10-27 17:55:16

Just an idea for horizontal menu...

Part of HTML

<div class='list'>
  <div class='item'>
  <div class='parent-background'></div>
  <!-- submenu takes this place -->

Part of CSS

/* Hide parent backgrounds... */
.parent-background {
  display: none; }

/* ... and show it when hover on children */
.item:hover + .parent-background {
  display: block;
  position: absolute;
  z-index: 10;
  top: 0;
  width: 100%; }

Updated demo and the rest of code

Another example how to use it with text-inputs - select parent fieldset

@Nathan Tuggy 2015-10-28 07:57:38

It's not at all clear to me how you mean to generalize this to some/many/most of the parent selector use cases, or even exactly which parts of this CSS are doing what. Can you add a thorough explanation?

@Ilya B. 2015-10-28 08:08:58

I did not try to apply this to real world scenarios, that is why I say "Not for production". But I think It can be applied to 2-level menu only with fixed item width. "which parts of this CSS are doing what" - .test-sibling here is actually background of parent item (the last line of CSS).

@Ilya B. 2015-10-28 12:59:48

Added explanation (css section of jsfiddle, starting from "MAIN PART")... And I was mistaken - there may be any number of sublevels.

@Prabhakar Undurthi 2015-10-14 10:08:04

Technically there is no direct way to do this. However, you can sort that out with either jQuery or JavaScript.

However, you can do something like this as well. h1 {color: blue;} p {color: green;}


$("").parents('li').css("property", "value");

If you want to achieve this using jQuery here is the reference for the jQuery parent selector.

@Marco Allori 2015-05-05 18:24:05

This is the most discussed aspect of the Selectors Level 4 specification. With this, a selector will be able to style an element according to its child by using an exclamation mark after the given selector (!).

For example:

body! a:hover{
   background: red;

will set a red background-color if the user hovers over any anchor.

But we have to wait for browsers' implementation :(

@Salman A 2014-01-21 08:43:47

There is no parent selector; just the way there is no previous sibling selector. One good reason for not having these selectors is because the browser has to traverse through all children of an element to determine whether or not a class should be applied. For example, if you wrote:

body:contains-selector( { background: red; }

Then the browser will have to wait until it has loaded and parsed everything until the </body> to determine if the page should be red or not.

The article Why we don't have a parent selector explains it in detail.

@vsync 2014-02-19 21:33:39

so make the browser faster. the internet itself faster. this selector is definitely needed, and the reason for not implementing it is, sadly, because we live in a slow, primitive world.

@Salman A 2014-02-20 04:09:48

actually, the selector would make a very fast browser look slow.

@Marc.2377 2018-06-09 00:15:36

I trust that browser developers would come up with an implementation which is (at least) as fast as the javascript version, which is the one people end up using anyway.

@Marvin 2019-05-05 19:26:07

"we live in a slow, primitive world" cough cough new apple watch cough cough

@xryl669 2019-09-07 12:41:18

@Marc.2377 If you try the above example in JS on your website, I'm never going to visit it. On the other side, I'd say that most of the time, you only care about immediate children, so if it was only limited to the immediate children, it'd be a good addition without too much impact.

@Raseko 2011-11-23 09:03:14

Try to switch a to block display, and then use any style you want. The a element will fill the li element, and you will be able to modify its look as you want. Don't forget to set li padding to 0.

li {
  padding: 0;
  overflow: hidden;
a {
  display: block;
  width: 100%;
  color: ..., background: ..., border-radius: ..., etc...
} {
  color: ..., background: ...

@Idered 2011-08-13 10:13:50

You can use this script:

*! > input[type=text] { background: #000; }

This will select any parent of a text input. But wait, there's still much more. If you want, you can select a specified parent:

.input-wrap! > input[type=text] { background: #000; }

Or select it when it's active:

.input-wrap! > input[type=text]:focus { background: #000; }

Check out this HTML:

<div class="input-wrap">
    <input type="text" class="Name"/>
    <span class="help hide">Your name sir</span>

You can select that when the input is active and show it:

.input-wrap! .help > input[type=text]:focus { display: block; }

There are many more capabilities; just check out the documentation of the plugin.

BTW, it works in Internet Explorer.

@Dan 2011-09-22 19:30:37

suppose using jquery patent() would be faster. This need testing, however

@yunzen 2013-04-16 15:33:22

@Idered It fails when you have CSS declaration of a Selector Subject with no child selector (#a! alone throws an error, #a! p works), and so the others will not works either because of Uncaught TypeError: Cannot call method 'split' of undefined: see

@Idered 2013-04-17 13:41:20

@HerrSerker I think #a! is an invalid selector, what should it select?

@yunzen 2013-04-17 15:31:45

@Idered I don't know. The spec doesn't say it is illegal. #a! should select itself. At least their should be no error in the JavaScript

@BoltClock 2013-05-02 15:35:48

Per my comment on the accepted answer, it looks like the polyfill may be required even in the near future after all, because the subject indicator may never be implemented by browsers in CSS.

@toddmo 2017-05-01 19:54:08

How would you then stick an :after on that parent?

@TylerH 2018-06-06 13:42:34

Please add the contents of the script here, otherwise this is useless when GitHub is down.

@jeroen 2009-06-18 20:08:22

I don’t think you can select the parent in CSS only.

But as you already seem to have an .active class, it would be easier to move that class to the li (instead of the a). That way you can access both the li and the a via CSS only.

@user914183 2011-08-26 13:46:58

You can't shift the pseudo selector to the list item, as it is not a focusable element. He's using the :active selector, so when the anchor is active he wants the list item to be affected. List items will never be in the active state. As an aside, it's unfortunate that such a selector doesn't exist. Getting a pure CSS menu to be fully keyboard accessible seems to be impossible without it (using sibling selectors you can make submenus created using nested lists to appear, but once the list gains focus it becomes hidden again). If there are any CSS-only solutions to this particular conun

@jeroen 2011-08-26 14:34:51

@Dominic Aquilina Take a look at the question, the OP is using a class, not a pseudo selector.

@Josh 2009-06-18 20:06:44

There isn't a way to do this in CSS 2. You could add the class to the li and reference the a: > a {
    property: value;

@Josh 2009-06-18 21:53:32

by making the a element display:block you can style it to fit the whole of the li area. if you can explain what style you are looking for perhaps I could help with a solution.

@Ricardo 2016-03-18 23:17:12

this is actually an simple and elegant solution and, in many cases, it makes sense to set the class on the parent.

@Sethuraman 2019-07-05 06:34:42

Changing parent element based on child element can currently only happen when we have an <input> element inside the parent element. When an input gets focus, its corresponding parent element can get affected using CSS.

Following example will help you understand using :focus-within in CSS.

.outer-div {
  width: 400px;
  height: 400px;
  padding: 50px;
  float: left

.outer-div:focus-within {
  background: red;

.inner-div {
  width: 200px;
  height: 200px;
  float: left;
  background: yellow;
  padding: 50px;
<div class="outer-div">
  <div class="inner-div">
    I want to change outer-div(Background color) class based on inner-div. Is it possible?
    <input type="text" placeholder="Name" />

@Dan Herbert 2009-06-18 20:16:50

There is currently no way to select the parent of an element in CSS.

If there was a way to do it, it would be in either of the current CSS selectors specs:

In the meantime, you'll have to resort to JavaScript if you need to select a parent element.

The Selectors Level 4 Working Draft includes a :has() pseudo-class that works the same as the jQuery implementation. As of 2019, this is still not supported by any browser.

Using :has() the original question could be solved with this:

li:has(> { /* styles to apply to the li tag */ }

@RobM 2010-10-27 12:22:32

It would seem that it has already been suggested and rejected:…

@animuson 2012-01-29 21:30:46

Looks like the subject selector has been revisited, except by using a ! now: The subject of the selector can be explicitly identified by appending an exclamation mark (!) to one of the compound selectors in a selector.

@Christoph 2012-02-13 11:25:52

The prepended $ looked better for me... the appended ! can be overlooked more easily.

@BoltClock 2012-02-20 17:15:45

@animuson, Christoph: Let's just wait until they've gone through a few more revisions of the draft...

@Dan Herbert 2012-02-20 18:08:33

@animuson I'm in agreement with BoltClock here. The reference I included is the working draft. It has only been changed in the editor's draft version of the spec. Once the new syntax has made its way into the working draft version I'll update my answer. Regardless of the syntax, no browser or JS framework has implemented this yet so the exact syntax isn't very important at the moment.

@BoltClock 2012-10-23 15:11:20

Just as a quickie, the Selectors 4 WD was updated a couple of months ago to include the new syntax. Of course, updating an "old" unusable sample to something that still can't be used anyway would be futile. Besides, they still haven't decided on the final syntax.

@Dan Herbert 2013-04-28 23:27:15

@codeninja The > selector works fine for me in Chrome. Are you sure there isn't something else going wrong? See this test:

@BoltClock 2013-05-02 15:19:51

Major plot twist! The Selectors 4 WD was just updated today to exclude the subject indicator from the fast profile, which is to be used by CSS implementations. If this change remains, it means you won't be able to use the subject indicator in stylesheets anymore (unless you use add some sort of polyfill like the one described in another answer) - you can only use it with the Selectors API and anywhere else that the complete profile may be implemented.

@David says reinstate Monica 2013-05-05 18:27:28

@BoltClock: I think I must be missing something, but from the latest spec (to which you've linked) it seems as if we have a subject-selector (yay, finally! And so forth) but we're unable to use it because it's not permitted in the 'fast' selectors; is there a point to this, or just a reserved selector for future use?

@BoltClock 2013-05-06 06:24:48

@David Thomas: I see what you mean. The point is that if it is possible to implement the subject indicator for use in selectors, then wherever selectors can be used without affecting the performance of other things (e.g. querySelectorAll(), matches() in selectors-api2), it should be implemented. Also, assuming the spec even allows it - it's not clear right now if it does or if it will - some browsers may even choose to implement the complete profile for CSS, though I suspect it'll be difficult to prove that it can be done in a way that doesn't adversely affect page rendering performance.

@BoltClock 2013-05-06 06:35:49

@David Thomas: Most people don't realize this, but the reason why Selectors was made its own module is that while selectors were originally conceived as part of CSS, they're now being used in numerous places other than stylesheets, such as libraries like jQuery and testing frameworks like Selenium. I think the gist of all this is to not let the nature of CSS implementations affect what sort of selectors can be defined for a wider variety of purposes.

@Paul S. 2013-11-13 13:25:54

If anyone reading this can give input to the draft, with ! seeming to be the chosen symbol now, how about making a lone ! an alias for !important in CSS attributes too. This way, when thinking in CSS, a ! has the uniform meaning of (something like) "I want this one". Building from this, appending in the selector might be preferable for uniformity, too. With the added advantage of knowing the difference between span!:nth-child(4) (span with 4 children) and span:nth-child(4)! (4th child of span). I hope these ideas can make it into the discussion!

@BoltClock 2013-12-18 09:58:57

@Paul S.: There are several fundamental issues with your proposal. First, since the subject selector might not even be usable in CSS, creating an alias of !important called ! probably isn't going to make a whole lot of sense. Furthermore, you can have more than one !important per property on the same element, but there can only be one subject per selector.

@BoltClock 2013-12-18 10:00:01

@Paul S.: Second, you've misunderstood the selector notation. span:nth-child(4) has only one meaning, and that is "span that is the 4th child". That's because you're attaching the pseudo-class to the element type, which works exactly like attaching an ID or a class to a type selector. Combining simple selectors like this results in a compound selector, which represents one element in a hierarchy, and the spec specifies that ! may only be attached to any one compound selector.

@BoltClock 2013-12-18 10:05:43

@Paul S.: If you want to select a span with 4 children, the correct selector would be span! > :nth-child(4), and if you want to select the 4th child of span, that would simply be span > :nth-child(4) (which is already a valid selector today). Each of these has two compound selectors: span, and :nth-child(4), and by default (as it already is with current CSS) the rightmost one is the subject which is what makes the ! optional in the latter case.

@BoltClock 2014-05-04 14:28:10

Another major update: it looks like they're considering doing away with the subject selector syntax altogether and replacing it with the :has() pseudo everybody has come to know and love from jQuery. The latest ED has removed all references to the subject indicator, and replaced it with the :has() pseudo. I don't know the exact reasons, but the CSSWG held a poll some time ago and the results must have influenced this decision. It's most likely for compatibility with jQuery (so it can leverage qSA without modifications), and because the subject indicator syntax proved too confusing.

@BoltClock 2014-05-04 14:30:06

So, the corresponding selector would be li:has(> Note that jQuery already supports relative selector syntax in :has(), although it isn't documented anywhere.

@WraithKenny 2014-10-10 19:22:34

It's a shame, $E elem looks way better, and is easier (faster) to understand then elem:has(E) and is functionally equivalent.

@osirisgothra 2014-11-28 12:50:11

its not css4, they need to stop saying css3 too, its just css from here on out. working draft or levels are okay, but the blatant labeling of 'css3' and 'css4' must stop or else everyone is going to start clucking them out like crazy. C-S-S...see?

@BoltClock 2015-01-20 19:27:02

@Juan: This has absolutely nothing to do with cascading.

@BoltClock 2015-01-20 19:28:26

@osirisgothra: Yeah, even the official definition of CSS3 is "anything beyond CSS2", which is completely meaningless in practice (and of course there is no "CSS4").

@BoltClock 2015-01-20 19:30:17

@WraithKenny: It was never actually made clear if it was going to be functionally equivalent. See my answer here for why I think they ultimately went with :has().

@WraithKenny 2015-01-28 02:30:25

@BoltClock I see what you are saying, but I'd prefer the more limited, simple (non-ascending) functionality, and the simpler syntax of the subject selector (selected from the same 'crawl'). I agree that those are two different functionalities, you are right.

@Juan 2015-02-19 04:40:26

@BoltClock thats my point. a "parent" selector in css should never exist, as its not cascading.. css is top down, not bottom up.

@Ajedi32 2015-10-27 18:52:15

@Juan That's not what "cascading" means in this context. Cascading has almost nothing to do with selectors. The stylesheets "cascade" in the sense that a { rule1: value; } .foo{ rule2: value2; } results in both rule1 and rule2 having their values set on an a element with a class of foo. The existence of a parent selector has no bearing on that.

@Juan 2015-10-28 19:53:22

@Ajedi32 I know the meaning of cascading. And imo it also applies here. Again, the whole language is based on top down rules, you can't start changing the foundation just because there is a very specific edge case that requires inspecting childrens. But its just my opinion.

@Dan Herbert 2015-10-29 20:38:38

@Juan Cascading isn't really the limitation for creating a "parent" selector in CSS. There are already sibling selectors, odd/even selectors, and a huge variety of selectors that refer to an element's state/placement that don't have any "top down" pattern. The real limitation is an implementation detail. Browsers have optimized selectors to be parsed forward-only, so any selector that requires backtracking would be inefficient. This is the same reason why there is a "next sibling" selector, but no "previous sibling" selector.

@BoltClock 2015-11-03 17:11:55

... how can something that's totally unrelated to selectors apply in this context?! How do you go from conflict resolution between two style declarations to matching a parent element in a selector?

@1.21 gigawatts 2017-06-15 17:19:09

@Mahi Implementing a parent selector is easy. When you are parsing a stylesheet and you come across a selector that targets it's parent you add that append list if you haven't built the DOM. As you build the DOM and you encounter the element then you can append the styles to the parent element's CSS stylesheet. If are parsing the stylesheet and the DOM is already created you simply add the styles to the parent element stylesheet. I happen to be working in this area so to me it's not that difficult. Just planning ahead.

@Alex78191 2017-06-19 00:17:15

When i can use it in Chrome?

@Dan Herbert 2017-07-10 19:17:33

@Alex78191 Nobody knows. It's not on Chrome's roadmap and the spec may change before any browser implements it. MS Edge has it "under consideration" but it will probably be years before it can be used.

@wha7ever 2017-10-02 16:47:54

@jhpratt GOFUNDME RELICENSING 2017-12-13 22:29:25

Worth noting that :has() will not be implemented in CSS, at least in the level 4 module. It is explicitly only to be implemented in JS.

@TylerH 2018-05-08 19:42:09

@jhpratt The world would be a very different place if browser vendors adhered strictly to the W3C's CSS specs.

@jhpratt GOFUNDME RELICENSING 2018-05-08 21:35:03

@TylerH For one, it's the CSSWG that creates specs. Regardless, the people writing specs are (for the most part) representatives of vendors. Specifically regarding the :has() selector or any other parent selector, implementation would fundamentally change the single-pass nature of CSS, which I don't expect to happen anytime soon. That's coming from someone who follows the WG's discussions relatively closely.

@TylerH 2018-05-09 13:51:06

@jhpratt You are preaching to the choir, buddy. I am aware of how the working groups operate and write specs, having worked with them and advocated for :has() (among many other things) for years.

@Grant Noe 2019-05-22 23:48:47

:has() still isn't a quality parent selector since technically you couldn't select a child without knowing who the parent was. Unless you could *:has().

@mbomb007 2019-08-02 13:59:19

@GrantNoe You can. In addition, using #myDiv:has(.class) gets all descendant elements with .class, not just elements where myDiv is the parent.

@Toolkit 2019-11-16 05:13:39

end of 2019 document.querySelectorAll('li:has(>') gives me Uncaught DOMException: Failed to execute 'querySelectorAll' on 'Document': 'li:has(>' is not a valid selector.

@sol 2017-09-25 13:55:34

The pseudo element :focus-within allows a parent to be selected if a descendent has focus.

An element can be focused if it has a tabindex attribute.

Browser support for focus-within



.click {
  cursor: pointer;

.color:focus-within .change {
  color: red;

.color:focus-within p {
  outline: 0;
<div class="color">
  <p class="change" tabindex="0">
    I will change color
  <p class="click" tabindex="1">
    Click me

@cancerbero 2018-06-29 15:13:57

This works fine in my case, thanks! Just a not, the example would be more ilustrative if you change the color to the parent, not to the sibling, this is replace .color:focus-within .change with .color:focus-within. In my case i'm using bootstrap nav-bar that add the class to the children when active and I want to add a class to the parent .nav-bar. I think this is a pretty common scenario where I own the markup but the component css+js is bootstrap (or other) so I cannot change the behavior. Although I can add tabindex and use this css. Thanks!

@Suraj Naik 2014-03-21 12:58:43

Currently there is no parent selector & it is not even being discussed in any of the talks of W3C. You need to understand how CSS is evaluated by the browser to actually understand if we need it or not.

There is a lot of technical explanation here.

Jonathan Snook explains how CSS is evaluated.

Chris Coyier on the talks of Parent selector.

Harry Roberts again on writing efficient CSS selectors.

But Nicole Sullivan has some interesting facts on positive trends.

These people are all top class in the field of front end development.

@nicodemus13 2014-05-15 09:04:41

The need is defined by web developers' requirements, whether to have it in the spec is decided by other factors.

@cobaasta 2011-06-30 14:00:09

The CSS selector “General Sibling Combinator” could maybe used for what you want:

E ~ F {
    property: value;

This matches any F element that is preceded by an E element.

@Alireza 2017-06-16 18:08:12

This is just sibling selector, it's not child, parent... not really answering the question mate

@Rounin 2017-02-18 17:06:00

Although there is no parent selector in standard CSS at present, I am working on a (personal) project called axe (ie. Augmented CSS Selector Syntax / ACSSSS) which, among its 7 new selectors, includes both:

  1. an immediate parent selector < (which enables the opposite selection to >)
  2. an any ancestor selector ^ (which enables the opposite selection to [SPACE])

axe is presently in a relatively early BETA stage of development.

See a demo here:

(compare the two lists on the left styled with standard selectors and the two lists on the right styled with axe selectors)

@Rounin 2017-07-12 16:40:34

The project is in an early Beta stage at present. You can (at least currently) activate axe selectors in your CSS styles by including <script src=""></script> at the very end of your html document, just before </body>.

@Sukhminder Parmar 2016-09-15 04:06:49

In CSS, we can cascade to the properties down the hierarchy but not in the oppostite direction. To modify the parent style on child event, probably use jQuery.


@David Clarke 2013-05-16 22:04:58

I know the OP was looking for a CSS solution but it is simple to achieve using jQuery. 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:


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


@Robin van Baalen 2013-07-18 17:40:39

Or use $yourSpan.closest("ul") and you'll get the parent UL of your span element. Nevertheless your answer is completely offtopic imho. We can answer all of the CSS-taged questions with a jQuery solution.

@David Clarke 2015-12-19 19:27:31

As identified in other answers, there is no way to do this using CSS 2. Given that constraint, the answer I provided is one I know is effective and is the simplest way to answer the question using javascript imho.

@Robin van Baalen 2015-12-19 19:36:50

Given your upvotes, some people agree with you. But the only answer remains the accepted one; plain and simple "it cant be done the way you want it". If the question is how to archieve 60mph on a bicycle and you answer it with "simple; get in a car and hit the gas.", it's still not an answer. Hence my comment.

@David Clarke 2015-12-20 18:35:37

That approach would make SO almost completely useless. I search SO for how to solve problems, not to find the "only answer" doesn't address the issue. That is why SO is so awesome, because there is always more than one way to skin a cat.

@zcrar70 2009-12-14 14:51:14

As mentioned by a couple of others, there isn't a way to style an element's parent/s using just CSS but the following works with jQuery:

$("").parents('li').css("property", "value");

@Rob W 2012-02-23 17:53:13

The < selector does not exist (verified using jQuery 1.7.1).

@Alastair 2013-05-02 05:10:13

Perhaps that <-syntax worked in 2009 but I've updated it (for 2013).

@Rory O'Kane 2013-05-08 22:12:06

Even better, use jQuery's built-in :has() selector: $("li:has(").css("property", "value");. It reads similarly to CSS 4's proposed ! selector. See also: :parent selector, .parents() method, .parent() method.

@Rory O'Kane 2013-05-08 22:20:12

And rather than using .css("property", "value") to style the selected elements, you should usually .addClass("someClass") and have in your CSS .someClass { property: value } (via). That way, you can notate the style with the full power of CSS and any preprocessors you are using.

@riverstorm 2012-02-13 11:22:34

You might try to use hyperlink as the parent, and then change the inner elements on hover. Like this: h1 {color:red;} h1 {color:green;} h2 {color:blue;} h1 {color:yellow;}

This way you can change the style in multiple inner tags, based on the rollover of the parent element.

@Ivaylo Slavov 2012-07-24 18:22:49

That is correct, but limits the markup code within the a tag to certain elements only, if you want to conform to XHTML standards. For instance, you cannot use a div within a, without getting a warning of violating the schema.

@riverstorm 2012-12-12 22:34:43

Totaly right Ivaylo! "a" is a non-block element, so can't use block elements inside it.

@Matthew James Taylor 2014-04-06 07:47:10

In HTML5 it is perfectly fine to put block elements inside links.

@BoltClock 2015-12-28 15:54:58

... if it was semantically wrong, they wouldn't have allowed it in HTML5 where it wasn't before.

Related Questions

Sponsored Content

17 Answered Questions

[SOLVED] CSS selector for first element with class

  • 2010-04-26 22:51:13
  • Rajat
  • 981366 View
  • 925 Score
  • 17 Answer
  • Tags:   css css-selectors

28 Answered Questions

[SOLVED] Set cellpadding and cellspacing in CSS?

16 Answered Questions

[SOLVED] Is there a "previous sibling" selector?

  • 2009-11-30 04:06:36
  • Jourkey
  • 656911 View
  • 1314 Score
  • 16 Answer
  • Tags:   css css-selectors

36 Answered Questions

[SOLVED] Change an HTML5 input's placeholder color with CSS

11 Answered Questions

[SOLVED] What does the "+" (plus sign) CSS selector mean?

  • 2009-07-16 19:26:50
  • gday
  • 310847 View
  • 739 Score
  • 11 Answer
  • Tags:   css css-selectors

9 Answered Questions

[SOLVED] Which characters are valid in CSS class names/selectors?

  • 2009-01-15 23:37:39
  • Darryl Hein
  • 373151 View
  • 1189 Score
  • 9 Answer
  • Tags:   css css-selectors

19 Answered Questions

[SOLVED] Is it possible to apply CSS to half of a character?

  • 2014-05-09 16:16:57
  • Mathew MacLean
  • 240015 View
  • 2778 Score
  • 19 Answer
  • Tags:   javascript html css

5 Answered Questions

[SOLVED] What does the "~" (tilde/squiggle/twiddle) CSS selector mean?

  • 2012-05-28 09:10:00
  • Akshat
  • 255967 View
  • 829 Score
  • 5 Answer
  • Tags:   css css-selectors

Sponsored Content