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 < a.active {
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).
The Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation, but is currently not supported by Firefox.
li:has(> a.active) { /* styles to apply to the li tag */ }
As of 2022, Firefox is the only browser not supporting it by default.
In the meantime, you'll have to resort to JavaScript in Firefox if you need to select a parent element with full cross-browser support.
You can use the :has() CSS pseudo-class
But it has limited browser support (Currently only Chrome / Edge / Safari).
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.
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>
</div>
You can select that span.help 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.
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:
$("a.active").parents('li').css("property", "value");
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(a.active) { 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.
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
Tabindex
Example
.parent:focus-within {
background: hsl(199deg, 65%, 73%);
}
/* demo styles */
body {
margin: 0;
}
.parent {
background: hsl(0, 0%, 80%);
min-height: 100vh;
display: grid;
place-content: center;
}
.child {
background: hsl(0, 0%, 0%);
color: white;
padding: 3rem;
outline: 0;
cursor: pointer;
font: 18px/1.25 sans-serif;
width: 20ch;
}
<div class="parent">
<div class="child" tabindex="1">
Click or Focus on me, my parent will change.
</div>
</div>
There isn't a way to do this in CSS 2. You could add the class to the li and reference the a:
li.active > a {
property: value;
}
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...
}
a.active {
color: ..., background: ...
}
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.
Not in CSS 2 as far as I'm aware. CSS 3 has more robust selectors but is not consistently implemented across all browsers. Even with the improved selectors, I don't believe it will accomplish exactly what you've specified in your example.
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 :(
You might try to use hyperlink as the parent, and then change the inner elements on hover. Like this:
a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}
This way you can change the style in multiple inner tags, based on the rollover of the parent element.
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:
$("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)")
Here's a hack using pointer-events with hover:
<!doctype html>
<html>
<head>
<title></title>
<style>
/* accessory */
.parent {
width: 200px;
height: 200px;
background: gray;
}
.parent,
.selector {
display: flex;
justify-content: center;
align-items: center;
}
.selector {
cursor: pointer;
background: silver;
width: 50%;
height: 50%;
}
</style>
<style>
/* pertinent */
.parent {
background: gray;
pointer-events: none;
}
.parent:hover {
background: fuchsia;
}
.parent
.selector {
pointer-events: auto;
}
</style>
</head>
<body>
<div class="parent">
<div class="selector"></div>
</div>
</body>
</html>
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 'a.active' {
$parent {
background: red;
}
}
So here we've opened an element query on every element a.active, 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.
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.
Just an idea for horizontal menu...
Part of HTML
<div class='list'>
<div class='item'>
<a>Link</a>
</div>
<div class='parent-background'></div>
<!-- submenu takes this place -->
</div>
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
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; }
*/
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 = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
if(x.parentNode.tagName === 'LI') {
x.parentNode.style.color = 'red'; // Your property: value;
}
});
Or a shorter way if you use jQuery in your application:
$('a.active').parents('li').css('color', 'red'); // Your property: value;
The W3C excluded such a selector because of the huge performance impact it would have on a browser.
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.
a.active h1 {color: blue;}
a.active p {color: green;}
jQuery
$("a.active").parents('li').css("property", "value");
If you want to achieve this using jQuery here is the reference for the jQuery parent selector.
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:
an immediate parent selector < (which enables the opposite selection to >)
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:
.parent {
float: left;
width: 180px;
height: 180px;
margin-right: 12px;
background-color: rgb(191, 191, 191);
}
.child {
width: 90px;
height: 90px;
margin: 45px;
padding-top: 12px;
font-family: sans-serif;
text-align: center;
font-size: 12px;
background-color: rgb(255, 255, 0);
}
.child.using-axe < .parent {
background-color: rgb(255, 0, 0);
}
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child using-axe">Here, the axe parent selector turns the outer square red.</div>
</div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
In the example above < is the immediate parent selector, so
.child.using-axe < .parent
means:
any immediate parent of .child.using-axe which is .parent
You could alternatively use:
.child.using-axe < div
which would mean:
any immediate parent of .child.using-axe which is a div
The CSS parent selector (also know as the :has() selector) has finally landed in Safari TP 137. The feature is currently being implementated in Chrome as well. (MDN Documentation)
Parent selection is done via the pseudo-class :has(). For example, div:has(> .child) will select all <div> elements with a child having a child class.
Other examples:
Selecting direct parent of an element
<div>
<p>Child Element</p>
</div>
div:has(> p)
Selecting all the parents of an element
<div id="grandparent">
<div id="parent">
<div id="child"></div>
<div>
</div>
The following selector will select both grandparent and parent
div:has(.child)
You can also use it for nested selectors and even with other pseudo classes:
div:has(> :nth-child(10))
Other valid CSS operators can be used to customize the query.
Keep an eye on caniuse.com/css-has for browser compatibility.
Updated 2022 CSS Selectors 4
In the CSS Selectors 4 specification, CSS introduces a new selector called :has(), which finally lets us select parents. That means is we’ll be able to target a CSS element that has specific children within it. This is already supported in Safari and is also in Chrome 105. The full support table is shown
here.
Parent Selectors workings
In CSS, if we want to select something, we use selectors that descend the DOM.
For example, selecting a p tag within a div tag looks like this:
div p {
color: red;
}
Until now, couldn’t really select the div tags which had p tags within them, though, and this meant we had to resort to Javascript. The main reason this wasn’t implemented in CSS is that it’s quite an expensive operation to do. CSS is relatively fast to parse, but selecting parent tags requires a relatively significantly larger amount of processing.
Using the :has selector, we can now select div elements which have a p children, or any normal combination of selectors.
For example, selecting a div with a child p now looks like this:
div:has(p) {
color: red;
}
This will make any div with a child p red.
Combining parent selection with other selectors
Just like any other CSS selector, we can combine this for specific circumstances.
For example, if you want to select only div tags which have direct span children:
div:has(> span) {
color: red;
}
As the vocabulary of :has suggested, it is not just limited to parent selection.
For example, below we can select a span which :has a sibling div:
span:has(+ div) {
color: red;
}
Or even, selecting an element which does not have a child, by using the :not() selector.
For example, the following will select any div which does not have a p child:
div:not(:has(p)) {
color: red;
}
Selecting elements that only contain text in CSS
One very common problem in CSS is that the :empty tag does not select elements that contain any text - so sometimes an element can contain one space, and :empty will not apply. The :has selector gives us the power to select elements that only contain text nodes and no other child elements.
Although this is not the perfect solution for simply :empty elements with spaces (as this will select any element with just text and no additional HTML DOM elements) - it does give us the ability to select DOM elements with only text nodes, which was not previously possible. We can achieve this with the following code:
div:not(:has(*)) {
background: green;
}
Any ideas?
CSS4 will be fancy if it adds some hooks into walking backwards. Until 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__checkbox__selection,
.menu__checkbox__style,
.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;
}
/* ▼ - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
content: '\2630';
display: inline-block;
}
*/
/* ▼ - 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:hover,
.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"
name="colorize"
class="menu__checkbox__style"
id="style-default">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-one">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-two">
<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
</p>
<input type="checkbox"
class="menu__checkbox__selection"
id="trigger-style-menu">
<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>
<li class="menu__option">
<label for="style-one"
class="menu__trigger__style">First Alternative Style</label>
</li>
<li class="menu__option">
<label for="style-two"
class="menu__trigger__style">Second Alternative Style</label>
</li>
</ul>
<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.
</p>
</div>
... 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 pseudo classes, 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.
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.
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');
[].forEach.call(cells, function (el) {
//console.log(el.nodeName)
if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
console.log(el)
};
});
<div>Peter</div>
<div>Jackson link</div>
<div>Philip</div>
<div>Pullman link</div>
Try this...
This solution uses plain CSS2 rules with no Javascript and works in all browsers, old and new. When clicked, the child anchor tag activates its active pseudo-class event. It then simply hides itself, allowing the active event to bubble up to the parent li tag who then restyles himself and reveals his anchor child again with a new style. The child has styled the parent.
Using your example:
<ul>
<li class="listitem">
<a class="link" href="#">This is a Link</a>
</li>
</ul>
Now apply these styles with the active pseudo-class on a to restyle the parent li tag when the link is clicked:
a.link {
display: inline-block;
color: white;
background-color: green;
text-decoration: none;
padding: 5px;
}
li.listitem {
display: inline-block;
margin: 0;
padding: 0;
background-color: transparent;
}
/* When this 'active' pseudo-class event below fires on click, it hides itself,
triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {
display: none;
}
.listitem:active {
background-color: blue;
}
.listitem:active a.link {
display: inline-block;
background-color: transparent;
}
You should see the link with a green background now change to the list item's blue background on click.
turns to
on click.
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" />
</div>
</div>
Related
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 < a.active {
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).
The Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation, but is currently not supported by Firefox.
li:has(> a.active) { /* styles to apply to the li tag */ }
As of 2022, Firefox is the only browser not supporting it by default.
In the meantime, you'll have to resort to JavaScript in Firefox if you need to select a parent element with full cross-browser support.
You can use the :has() CSS pseudo-class
But it has limited browser support (Currently only Chrome / Edge / Safari).
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.
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>
</div>
You can select that span.help 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.
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:
$("a.active").parents('li').css("property", "value");
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(a.active) { 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.
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
Tabindex
Example
.parent:focus-within {
background: hsl(199deg, 65%, 73%);
}
/* demo styles */
body {
margin: 0;
}
.parent {
background: hsl(0, 0%, 80%);
min-height: 100vh;
display: grid;
place-content: center;
}
.child {
background: hsl(0, 0%, 0%);
color: white;
padding: 3rem;
outline: 0;
cursor: pointer;
font: 18px/1.25 sans-serif;
width: 20ch;
}
<div class="parent">
<div class="child" tabindex="1">
Click or Focus on me, my parent will change.
</div>
</div>
There isn't a way to do this in CSS 2. You could add the class to the li and reference the a:
li.active > a {
property: value;
}
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...
}
a.active {
color: ..., background: ...
}
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.
Not in CSS 2 as far as I'm aware. CSS 3 has more robust selectors but is not consistently implemented across all browsers. Even with the improved selectors, I don't believe it will accomplish exactly what you've specified in your example.
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 :(
You might try to use hyperlink as the parent, and then change the inner elements on hover. Like this:
a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}
This way you can change the style in multiple inner tags, based on the rollover of the parent element.
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:
$("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)")
Here's a hack using pointer-events with hover:
<!doctype html>
<html>
<head>
<title></title>
<style>
/* accessory */
.parent {
width: 200px;
height: 200px;
background: gray;
}
.parent,
.selector {
display: flex;
justify-content: center;
align-items: center;
}
.selector {
cursor: pointer;
background: silver;
width: 50%;
height: 50%;
}
</style>
<style>
/* pertinent */
.parent {
background: gray;
pointer-events: none;
}
.parent:hover {
background: fuchsia;
}
.parent
.selector {
pointer-events: auto;
}
</style>
</head>
<body>
<div class="parent">
<div class="selector"></div>
</div>
</body>
</html>
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 'a.active' {
$parent {
background: red;
}
}
So here we've opened an element query on every element a.active, 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.
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.
Just an idea for horizontal menu...
Part of HTML
<div class='list'>
<div class='item'>
<a>Link</a>
</div>
<div class='parent-background'></div>
<!-- submenu takes this place -->
</div>
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
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; }
*/
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 = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
if(x.parentNode.tagName === 'LI') {
x.parentNode.style.color = 'red'; // Your property: value;
}
});
Or a shorter way if you use jQuery in your application:
$('a.active').parents('li').css('color', 'red'); // Your property: value;
The W3C excluded such a selector because of the huge performance impact it would have on a browser.
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.
a.active h1 {color: blue;}
a.active p {color: green;}
jQuery
$("a.active").parents('li').css("property", "value");
If you want to achieve this using jQuery here is the reference for the jQuery parent selector.
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:
an immediate parent selector < (which enables the opposite selection to >)
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:
.parent {
float: left;
width: 180px;
height: 180px;
margin-right: 12px;
background-color: rgb(191, 191, 191);
}
.child {
width: 90px;
height: 90px;
margin: 45px;
padding-top: 12px;
font-family: sans-serif;
text-align: center;
font-size: 12px;
background-color: rgb(255, 255, 0);
}
.child.using-axe < .parent {
background-color: rgb(255, 0, 0);
}
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child using-axe">Here, the axe parent selector turns the outer square red.</div>
</div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
In the example above < is the immediate parent selector, so
.child.using-axe < .parent
means:
any immediate parent of .child.using-axe which is .parent
You could alternatively use:
.child.using-axe < div
which would mean:
any immediate parent of .child.using-axe which is a div
The CSS parent selector (also know as the :has() selector) has finally landed in Safari TP 137. The feature is currently being implementated in Chrome as well. (MDN Documentation)
Parent selection is done via the pseudo-class :has(). For example, div:has(> .child) will select all <div> elements with a child having a child class.
Other examples:
Selecting direct parent of an element
<div>
<p>Child Element</p>
</div>
div:has(> p)
Selecting all the parents of an element
<div id="grandparent">
<div id="parent">
<div id="child"></div>
<div>
</div>
The following selector will select both grandparent and parent
div:has(.child)
You can also use it for nested selectors and even with other pseudo classes:
div:has(> :nth-child(10))
Other valid CSS operators can be used to customize the query.
Keep an eye on caniuse.com/css-has for browser compatibility.
Updated 2022 CSS Selectors 4
In the CSS Selectors 4 specification, CSS introduces a new selector called :has(), which finally lets us select parents. That means is we’ll be able to target a CSS element that has specific children within it. This is already supported in Safari and is also in Chrome 105. The full support table is shown
here.
Parent Selectors workings
In CSS, if we want to select something, we use selectors that descend the DOM.
For example, selecting a p tag within a div tag looks like this:
div p {
color: red;
}
Until now, couldn’t really select the div tags which had p tags within them, though, and this meant we had to resort to Javascript. The main reason this wasn’t implemented in CSS is that it’s quite an expensive operation to do. CSS is relatively fast to parse, but selecting parent tags requires a relatively significantly larger amount of processing.
Using the :has selector, we can now select div elements which have a p children, or any normal combination of selectors.
For example, selecting a div with a child p now looks like this:
div:has(p) {
color: red;
}
This will make any div with a child p red.
Combining parent selection with other selectors
Just like any other CSS selector, we can combine this for specific circumstances.
For example, if you want to select only div tags which have direct span children:
div:has(> span) {
color: red;
}
As the vocabulary of :has suggested, it is not just limited to parent selection.
For example, below we can select a span which :has a sibling div:
span:has(+ div) {
color: red;
}
Or even, selecting an element which does not have a child, by using the :not() selector.
For example, the following will select any div which does not have a p child:
div:not(:has(p)) {
color: red;
}
Selecting elements that only contain text in CSS
One very common problem in CSS is that the :empty tag does not select elements that contain any text - so sometimes an element can contain one space, and :empty will not apply. The :has selector gives us the power to select elements that only contain text nodes and no other child elements.
Although this is not the perfect solution for simply :empty elements with spaces (as this will select any element with just text and no additional HTML DOM elements) - it does give us the ability to select DOM elements with only text nodes, which was not previously possible. We can achieve this with the following code:
div:not(:has(*)) {
background: green;
}
Any ideas?
CSS4 will be fancy if it adds some hooks into walking backwards. Until 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__checkbox__selection,
.menu__checkbox__style,
.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;
}
/* ▼ - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
content: '\2630';
display: inline-block;
}
*/
/* ▼ - 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:hover,
.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"
name="colorize"
class="menu__checkbox__style"
id="style-default">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-one">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-two">
<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
</p>
<input type="checkbox"
class="menu__checkbox__selection"
id="trigger-style-menu">
<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>
<li class="menu__option">
<label for="style-one"
class="menu__trigger__style">First Alternative Style</label>
</li>
<li class="menu__option">
<label for="style-two"
class="menu__trigger__style">Second Alternative Style</label>
</li>
</ul>
<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.
</p>
</div>
... 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 pseudo classes, 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.
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.
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');
[].forEach.call(cells, function (el) {
//console.log(el.nodeName)
if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
console.log(el)
};
});
<div>Peter</div>
<div>Jackson link</div>
<div>Philip</div>
<div>Pullman link</div>
Try this...
This solution uses plain CSS2 rules with no Javascript and works in all browsers, old and new. When clicked, the child anchor tag activates its active pseudo-class event. It then simply hides itself, allowing the active event to bubble up to the parent li tag who then restyles himself and reveals his anchor child again with a new style. The child has styled the parent.
Using your example:
<ul>
<li class="listitem">
<a class="link" href="#">This is a Link</a>
</li>
</ul>
Now apply these styles with the active pseudo-class on a to restyle the parent li tag when the link is clicked:
a.link {
display: inline-block;
color: white;
background-color: green;
text-decoration: none;
padding: 5px;
}
li.listitem {
display: inline-block;
margin: 0;
padding: 0;
background-color: transparent;
}
/* When this 'active' pseudo-class event below fires on click, it hides itself,
triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {
display: none;
}
.listitem:active {
background-color: blue;
}
.listitem:active a.link {
display: inline-block;
background-color: transparent;
}
You should see the link with a green background now change to the list item's blue background on click.
turns to
on click.
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" />
</div>
</div>
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 < a.active {
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).
The Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation, but is currently not supported by Firefox.
li:has(> a.active) { /* styles to apply to the li tag */ }
As of 2022, Firefox is the only browser not supporting it by default.
In the meantime, you'll have to resort to JavaScript in Firefox if you need to select a parent element with full cross-browser support.
You can use the :has() CSS pseudo-class
But it has limited browser support (Currently only Chrome / Edge / Safari).
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.
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>
</div>
You can select that span.help 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.
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:
$("a.active").parents('li').css("property", "value");
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(a.active) { 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.
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
Tabindex
Example
.parent:focus-within {
background: hsl(199deg, 65%, 73%);
}
/* demo styles */
body {
margin: 0;
}
.parent {
background: hsl(0, 0%, 80%);
min-height: 100vh;
display: grid;
place-content: center;
}
.child {
background: hsl(0, 0%, 0%);
color: white;
padding: 3rem;
outline: 0;
cursor: pointer;
font: 18px/1.25 sans-serif;
width: 20ch;
}
<div class="parent">
<div class="child" tabindex="1">
Click or Focus on me, my parent will change.
</div>
</div>
There isn't a way to do this in CSS 2. You could add the class to the li and reference the a:
li.active > a {
property: value;
}
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...
}
a.active {
color: ..., background: ...
}
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.
Not in CSS 2 as far as I'm aware. CSS 3 has more robust selectors but is not consistently implemented across all browsers. Even with the improved selectors, I don't believe it will accomplish exactly what you've specified in your example.
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 :(
You might try to use hyperlink as the parent, and then change the inner elements on hover. Like this:
a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}
This way you can change the style in multiple inner tags, based on the rollover of the parent element.
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:
$("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)")
Here's a hack using pointer-events with hover:
<!doctype html>
<html>
<head>
<title></title>
<style>
/* accessory */
.parent {
width: 200px;
height: 200px;
background: gray;
}
.parent,
.selector {
display: flex;
justify-content: center;
align-items: center;
}
.selector {
cursor: pointer;
background: silver;
width: 50%;
height: 50%;
}
</style>
<style>
/* pertinent */
.parent {
background: gray;
pointer-events: none;
}
.parent:hover {
background: fuchsia;
}
.parent
.selector {
pointer-events: auto;
}
</style>
</head>
<body>
<div class="parent">
<div class="selector"></div>
</div>
</body>
</html>
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 'a.active' {
$parent {
background: red;
}
}
So here we've opened an element query on every element a.active, 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.
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.
Just an idea for horizontal menu...
Part of HTML
<div class='list'>
<div class='item'>
<a>Link</a>
</div>
<div class='parent-background'></div>
<!-- submenu takes this place -->
</div>
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
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; }
*/
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 = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
if(x.parentNode.tagName === 'LI') {
x.parentNode.style.color = 'red'; // Your property: value;
}
});
Or a shorter way if you use jQuery in your application:
$('a.active').parents('li').css('color', 'red'); // Your property: value;
The W3C excluded such a selector because of the huge performance impact it would have on a browser.
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.
a.active h1 {color: blue;}
a.active p {color: green;}
jQuery
$("a.active").parents('li').css("property", "value");
If you want to achieve this using jQuery here is the reference for the jQuery parent selector.
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:
an immediate parent selector < (which enables the opposite selection to >)
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:
.parent {
float: left;
width: 180px;
height: 180px;
margin-right: 12px;
background-color: rgb(191, 191, 191);
}
.child {
width: 90px;
height: 90px;
margin: 45px;
padding-top: 12px;
font-family: sans-serif;
text-align: center;
font-size: 12px;
background-color: rgb(255, 255, 0);
}
.child.using-axe < .parent {
background-color: rgb(255, 0, 0);
}
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child using-axe">Here, the axe parent selector turns the outer square red.</div>
</div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
In the example above < is the immediate parent selector, so
.child.using-axe < .parent
means:
any immediate parent of .child.using-axe which is .parent
You could alternatively use:
.child.using-axe < div
which would mean:
any immediate parent of .child.using-axe which is a div
The CSS parent selector (also know as the :has() selector) has finally landed in Safari TP 137. The feature is currently being implementated in Chrome as well. (MDN Documentation)
Parent selection is done via the pseudo-class :has(). For example, div:has(> .child) will select all <div> elements with a child having a child class.
Other examples:
Selecting direct parent of an element
<div>
<p>Child Element</p>
</div>
div:has(> p)
Selecting all the parents of an element
<div id="grandparent">
<div id="parent">
<div id="child"></div>
<div>
</div>
The following selector will select both grandparent and parent
div:has(.child)
You can also use it for nested selectors and even with other pseudo classes:
div:has(> :nth-child(10))
Other valid CSS operators can be used to customize the query.
Keep an eye on caniuse.com/css-has for browser compatibility.
Updated 2022 CSS Selectors 4
In the CSS Selectors 4 specification, CSS introduces a new selector called :has(), which finally lets us select parents. That means is we’ll be able to target a CSS element that has specific children within it. This is already supported in Safari and is also in Chrome 105. The full support table is shown
here.
Parent Selectors workings
In CSS, if we want to select something, we use selectors that descend the DOM.
For example, selecting a p tag within a div tag looks like this:
div p {
color: red;
}
Until now, couldn’t really select the div tags which had p tags within them, though, and this meant we had to resort to Javascript. The main reason this wasn’t implemented in CSS is that it’s quite an expensive operation to do. CSS is relatively fast to parse, but selecting parent tags requires a relatively significantly larger amount of processing.
Using the :has selector, we can now select div elements which have a p children, or any normal combination of selectors.
For example, selecting a div with a child p now looks like this:
div:has(p) {
color: red;
}
This will make any div with a child p red.
Combining parent selection with other selectors
Just like any other CSS selector, we can combine this for specific circumstances.
For example, if you want to select only div tags which have direct span children:
div:has(> span) {
color: red;
}
As the vocabulary of :has suggested, it is not just limited to parent selection.
For example, below we can select a span which :has a sibling div:
span:has(+ div) {
color: red;
}
Or even, selecting an element which does not have a child, by using the :not() selector.
For example, the following will select any div which does not have a p child:
div:not(:has(p)) {
color: red;
}
Selecting elements that only contain text in CSS
One very common problem in CSS is that the :empty tag does not select elements that contain any text - so sometimes an element can contain one space, and :empty will not apply. The :has selector gives us the power to select elements that only contain text nodes and no other child elements.
Although this is not the perfect solution for simply :empty elements with spaces (as this will select any element with just text and no additional HTML DOM elements) - it does give us the ability to select DOM elements with only text nodes, which was not previously possible. We can achieve this with the following code:
div:not(:has(*)) {
background: green;
}
Any ideas?
CSS4 will be fancy if it adds some hooks into walking backwards. Until 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__checkbox__selection,
.menu__checkbox__style,
.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;
}
/* ▼ - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
content: '\2630';
display: inline-block;
}
*/
/* ▼ - 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:hover,
.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"
name="colorize"
class="menu__checkbox__style"
id="style-default">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-one">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-two">
<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
</p>
<input type="checkbox"
class="menu__checkbox__selection"
id="trigger-style-menu">
<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>
<li class="menu__option">
<label for="style-one"
class="menu__trigger__style">First Alternative Style</label>
</li>
<li class="menu__option">
<label for="style-two"
class="menu__trigger__style">Second Alternative Style</label>
</li>
</ul>
<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.
</p>
</div>
... 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 pseudo classes, 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.
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.
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');
[].forEach.call(cells, function (el) {
//console.log(el.nodeName)
if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
console.log(el)
};
});
<div>Peter</div>
<div>Jackson link</div>
<div>Philip</div>
<div>Pullman link</div>
Try this...
This solution uses plain CSS2 rules with no Javascript and works in all browsers, old and new. When clicked, the child anchor tag activates its active pseudo-class event. It then simply hides itself, allowing the active event to bubble up to the parent li tag who then restyles himself and reveals his anchor child again with a new style. The child has styled the parent.
Using your example:
<ul>
<li class="listitem">
<a class="link" href="#">This is a Link</a>
</li>
</ul>
Now apply these styles with the active pseudo-class on a to restyle the parent li tag when the link is clicked:
a.link {
display: inline-block;
color: white;
background-color: green;
text-decoration: none;
padding: 5px;
}
li.listitem {
display: inline-block;
margin: 0;
padding: 0;
background-color: transparent;
}
/* When this 'active' pseudo-class event below fires on click, it hides itself,
triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {
display: none;
}
.listitem:active {
background-color: blue;
}
.listitem:active a.link {
display: inline-block;
background-color: transparent;
}
You should see the link with a green background now change to the list item's blue background on click.
turns to
on click.
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" />
</div>
</div>
I have three different Links that all lead to the same page. But I need the page to load with different CSS settings (depending on which link was clicked, certain elements should be hidden on the new page).
Is that possible? Thank you!
Sure, you can use the :target pseudo-class to do so.
From MDN:
The :target CSS pseudo-class represents a unique element (the target element) with an id matching the URL's fragment.
With target, you click a link, like page.html#some-condition, and in your CSS, listen for that condition. When the id matches the hash in the address bar, you have a match and the target is met.
A link
<div id="some-condition"></div>
#some-condition:target {
/* style appropriately */
}
Here's a quick demo. In this case, the links contain the ids, but as demonstrated above, you can structure things however you'd like.
#red:target ~ .result {
background-color: red;
}
#blue:target ~ .result {
background-color: blue;
}
#green:target ~ .result {
background-color: green;
}
.result {
width: 100px;
height: 100px;
display: inline-block;
border: 1px solid;
background-color: #fff;
transition: 0.3s background-color;
}
<a id="red" href="#red">Red</a>
<a id="blue" href="#blue">Blue</a>
<a id="green" href="#green">Green</a>
<div class="result"></div>
jsFiddle
The plus sign selector (+) is for selecting the next adjacent sibling.
Is there an equivalent for the previous sibling?
No, there is no "previous sibling" selector.
On a related note, ~ is for general successor sibling (meaning the element comes after this one, but not necessarily immediately after) and is a CSS3 selector. + is for next sibling and is CSS2.1.
See Adjacent sibling combinator from Selectors Level 3 and 5.7 Adjacent sibling selectors from Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification.
I found a way to style all previous siblings (opposite of ~) that may work depending on what you need.
Let's say you have a list of links and when hovering on one, all the previous ones should turn red. You can do it like this:
/* default link color is blue */
.parent a {
color: blue;
}
/* prev siblings should be red */
.parent:hover a {
color: red;
}
.parent a:hover,
.parent a:hover ~ a {
color: blue;
}
<div class="parent">
link
link
link
link
link
</div>
Selectors level 4 proposes :has() (previously the subject indicator !) which will, one day, allow you to select a previous sibling with:
previous:has(+ next) {}
or (for a general previous sibling rather than adjacent one):
previous:has(~ next) {}
At the time of writing :has{} is supported by most but not all major browsers. Support is improving.
Over the years this answer has attracted dozens of "It's still not supported" comments (now deleted). Please don't add any more. There's a link to an regularly updated browser support chart in the answer.
Consider the order property of flex and grid layouts.
I'll focus on flexbox in the examples below, but the same concepts apply to Grid.
With flexbox, a previous sibling selector can be simulated.
In particular, the flex order property can move elements around the screen.
Here's an example:
You want element A to turn red when element B is hovered.
<ul>
<li>A</li>
<li>B</li>
</ul>
STEPS
Make the ul a flex container.
ul { display: flex; }
Reverse the order of siblings in the mark-up.
<ul>
<li>B</li>
<li>A</li>
</ul>
Use a sibling selector to target Element A (~ or + will do) .
li:hover + li { background-color: red; }
Use the flex order property to restore the order of siblings on the visual display.
li:last-child { order: -1; }
...and voilà! A previous sibling selector is born (or at least simulated).
Here's the full code:
ul {
display: flex;
}
li:hover + li {
background-color: red;
}
li:last-child {
order: -1;
}
/* non-essential decorative styles */
li {
height: 200px;
width: 200px;
background-color: aqua;
margin: 5px;
list-style-type: none;
cursor: pointer;
}
<ul>
<li>B</li>
<li>A</li>
</ul>
From the flexbox spec:
5.4. Display Order: the order property
Flex items are, by default, displayed and laid out in the same order as they appear in the source document. The
order property can be used to change this ordering.
The order property controls the order in which flex items appear within the flex container, by assigning them to ordinal groups. It takes a single <integer> value, which specifies which ordinal group the flex item
belongs to.
The initial order value for all flex items is 0.
Also see order in the CSS Grid Layout spec.
Examples of "previous sibling selectors" created with the flex order property.
.container { display: flex; }
.box5 { order: 1; }
.box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }
.box6 { order: -4; }
.box7 { order: -3; }
.box8 { order: -2; }
.box9 { order: -1; }
.box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;
font-size: 1.5em; }
.box12 { order: 2; }
.box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;
font-size: 1.5em; }
.box21 { order: 1; }
.box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }
/* non-essential decorative styles */
.container {
padding: 5px;
background-color: #888;
}
.box {
height: 50px;
width: 75px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
cursor: pointer;
}
<p>
Using the flex <code>order</code> property to construct a previous sibling selector
</p>
<div class="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
<div class="box box3"><span>3</span></div>
<div class="box box5"><span>HOVER ME</span></div>
<div class="box box4"><span>4</span></div>
</div>
<br>
<div class="container">
<div class="box box9"><span>HOVER ME</span></div>
<div class="box box12"><span>HOVER ME</span></div>
<div class="box box6"><span>6</span></div>
<div class="box box7"><span>7</span></div>
<div class="box box8"><span>8</span></div>
<div class="box box10"><span>10</span></div>
<div class="box box11"><span>11</span></div>
</div>
<br>
<div class="container">
<div class="box box21"><span>HOVER ME</span></div>
<div class="box box13"><span>13</span></div>
<div class="box box14"><span>14</span></div>
<div class="box box15"><span>15</span></div>
<div class="box box16"><span>16</span></div>
<div class="box box17"><span>17</span></div>
<div class="box box18"><span>18</span></div>
<div class="box box19"><span>19</span></div>
<div class="box box20"><span>20</span></div>
</div>
jsFiddle
A Side Note – Two Outdated Beliefs about CSS
Flexbox is shattering long-held beliefs about CSS.
One such belief is that a previous sibling selector is not possible in CSS.
To say this belief is widespread would be an understatement. Here's a sampling of related questions on Stack Overflow alone:
Select the preceding sibling of an element in CSS using selectors
CSS: select previous sibling
CSS select previous sibling
Previous adjacent selector in CSS
Select previous siblings on hover
CSS selector to get preceding sibling
Change color of sibling elements on hover using CSS
How to select the previous sibling using selenium css syntax
CSS Selector for selecting an element that comes BEFORE another element?
How to add styling to active input's previous sibling using CSS only
CSS selector for next and previous elements
How to affect other elements when a div is hovered
As described above, this belief is not entirely true. A previous sibling selector can be simulated in CSS using the flex order property.
The z-index Myth
Another long-standing belief has been that z-index works only on positioned elements.
In fact, the most current version of the spec – the W3C Editor's Draft – still asserts this to be true:
9.9.1 Specifying the stack level: the z-index
property
z-index
Value: auto | | inherit
Initial: auto
Applies to: positioned elements
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specified
(emphasis added)
In reality, however, this information is obsolete and inaccurate.
Elements that are flex items or grid items can create stacking contexts even when position is static.
4.3. Flex Item Z-Ordering
Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw
document order, and z-index values other than auto create a stacking context even if position is static.
5.4. Z-axis Ordering: the z-index property
The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is
used in place of raw document order, and z-index values other than auto create a stacking context even if
position is static.
Here's a demonstration of z-index working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/
I had the same question, but then I had a "duh" moment. Instead of writing
x ~ y
write
y ~ x
Obviously this matches "x" instead of "y", but it answers the "is there a match?" question, and simple DOM traversal may get you to the right element more efficiently than looping in javascript.
I realize that the original question was a CSS question so this answer is probably completely irrelevant, but other Javascript users may stumble on the question via search like I did.
There's not "previous selector", but you can use the combination of :not and ~ ("after selector"). No reverse order, no javascript.
.parent a{
color: blue
}
.parent a.active{
color: red
}
.parent a:not(.parent a.active ~ a){
color: red
}
<div class="parent">
link
link
link
link
link
</div>
I think my approach is more straight-forward than "style all divs, than remove styling for after divs", or using javascript, or using reverse order.
Three tricks:
basically, reversing the HTML order of your elements in HTML,
and using the ~ Next siblings operator:
1. Using CSS Flex and row-reverse
.reverse {
display: inline-flex;
flex-direction: row-reverse;
}
.reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
background:gold;
}
Hover a SPAN and see the previous elements being styled!<br>
<div class="reverse">
<!-- Reverse the order of inner elements -->
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
2. Using Flex with direction: RTL
.reverse {
display: inline-flex;
direction: rtl;
}
.reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
background: red;
}
Hover a SPAN and see the previous elements being styled!<br>
<div class="reverse">
<!-- Reverse the order of inner elements -->
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
3. Using float right
.reverse {
display: inline-block;
}
.reverse span{
float: right;
}
.reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
background: red;
}
Hover a SPAN and see the previous elements being styled!<br>
<div class="reverse">
<!-- Reverse the order of inner elements -->
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
+ is for the next sibling. Is there an equivalent for the previous
sibling?
You can use the two axe selectors: ! and ?
There are 2 subsequent sibling selectors in conventional CSS:
+ is the immediate subsequent sibling selector
~ is the any subsequent sibling selector
In conventional CSS, there is no previous sibling selector.
However, in the axe CSS post-processor library, there are 2 previous sibling selectors:
? is the immediate previous sibling selector (opposite of +)
! is the any previous sibling selector (opposite of ~)
Working Example:
In the example below:
.any-subsequent:hover ~ div selects any subsequent div
.immediate-subsequent:hover + div selects the immediate subsequent div
.any-previous:hover ! div selects any previous div
.immediate-previous:hover ? div selects the immediate previous div
div {
display: inline-block;
width: 60px;
height: 100px;
color: rgb(255, 255, 255);
background-color: rgb(255, 0, 0);
text-align: center;
vertical-align: top;
cursor: pointer;
opacity: 0;
transition: opacity 0.6s ease-out;
}
code {
display: block;
margin: 4px;
font-size: 24px;
line-height: 24px;
background-color: rgba(0, 0, 0, 0.5);
}
div:nth-of-type(-n+4) {
background-color: rgb(0, 0, 255);
}
div:nth-of-type(n+3):nth-of-type(-n+6) {
opacity: 1;
}
.any-subsequent:hover ~ div,
.immediate-subsequent:hover + div,
.any-previous:hover ! div,
.immediate-previous:hover ? div {
opacity: 1;
}
<h2>Hover over any of the blocks below</h2>
<div></div>
<div></div>
<div class="immediate-previous">Hover for <code>?</code> selector</div>
<div class="any-previous">Hover for <code>!</code> selector</div>
<div class="any-subsequent">Hover for <code>~</code> selector</div>
<div class="immediate-subsequent">Hover for <code>+</code> selector</div>
<div></div>
<div></div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
Another flexbox solution
You can use inverse the order of elements in HTML. Then besides using order as in Michael_B's answer you can use flex-direction: row-reverse; or flex-direction: column-reverse; depending on your layout.
Working sample:
.flex {
display: flex;
flex-direction: row-reverse;
/* Align content at the "reversed" end i.e. beginning */
justify-content: flex-end;
}
/* On hover target its "previous" elements */
.flex-item:hover ~ .flex-item {
background-color: lime;
}
/* styles just for demo */
.flex-item {
background-color: orange;
color: white;
padding: 20px;
font-size: 3rem;
border-radius: 50%;
}
<div class="flex">
<div class="flex-item">5</div>
<div class="flex-item">4</div>
<div class="flex-item">3</div>
<div class="flex-item">2</div>
<div class="flex-item">1</div>
</div>
There is no official way to do that at the moment but you can use a little trick to achieve this ! Remember that it is experimental and it has some limitation ...
(check this link if you worries about navigator compatibility )
What you can do is use a CSS3 selector : the pseudo classe called nth-child()
#list>* {
display: inline-block;
padding: 20px 28px;
margin-right: 5px;
border: 1px solid #bbb;
background: #ddd;
color: #444;
margin: 0.4em 0;
}
#list :nth-child(-n+4) {
color: #600b90;
border: 1px dashed red;
background: orange;
}
<p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>
<div id="list">
<span>1</span><!-- this will be selected -->
<p>2</p><!-- this will be selected -->
<p>3</p><!-- this will be selected -->
<div>4</div><!-- this will be selected -->
<div>5</div>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
</div>
Limitations
You can't select previous elements based on the classes of the next elements
This is the same for pseudo classes
You could use double negation
SELECTOR:not([SELECTOR]FILTER):not([SELECTOR]FILTER + SELECTOR) { ... }
Replace SELECTOR with either the TAG or .CLASS ( Using #ID is probably too specific ).
Replace FILTER with some other :PSUEDO-SELECTOR (I've only tried :hover) or .CLASS (More for toggling through Javascript).
Since the typical usage will probably rely upon hovering (See example that follows)
/* Effect only limited when hovering */
TAG.CLASS:not(TAG.CLASS:hover):not(TAG.CLASS:hover + TAG.CLASS) {}
/* Effect only applied when hovering */
PARENT.CLASS:hover > CHILD.CLASS:not(CHILD.CLASS:hover):not(CHILD.CLASS:hover + CHILD.CLASS) {}
/* Solution */
div.parent:hover > div.child:not(:hover):not(:hover ~ .child) {
background-color:red;
border-radius:1.5em;
}
div.parent:hover > div.child:not(:hover):not(:hover ~ .child) > div {
background-color:yellow;
}
/* Make pretty (kinda) */
div.parent {
width:9em;
height:9em;
/* Layout */
display:grid;
grid-template-columns : auto auto auto;
grid-template-rows : auto auto auto;
}
div.child {
/* Dimensions */
height:3em;
width:3em;
/* Layout */
position:relative;
/* Cursor */
cursor: pointer;
/* Presentation */
border: 1px black solid;
border-radius:1.5em;
}
.star {
/* Dimensions */
width: 2.5em;
height: 2.5em;
/* Placement */
position:absolute;
top: 50%;
left: 50%;
transform:translate(-50%,-50%);
/* Geometry */
-webkit-clip-path: polygon(
50% 0%,
63% 38%,
100% 38%,
69% 59%,
82% 100%,
50% 75%,
18% 100%,
31% 59%,
0% 38%,
37% 38%
);
clip-path: polygon(
50% 0%,
63% 38%,
100% 38%,
69% 59%,
82% 100%,
50% 75%,
18% 100%,
31% 59%,
0% 38%,
37% 38%
);
/* Presentation */
background-color: lightgrey;
}
div.child:hover {
/* Presentation */
background-color:yellow;
border-radius:1.5em;
}
div.child:hover > div.star {
/* Presentation */
background-color:red;
}
<div class="parent">
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
<div class="child" href="#"><div class="star"></div></div>
</div>
Overriding the styles of next siblings on hover, so that it looks like only previous siblings have styles added on hover.
ul li {
color: red;
}
ul:hover li {
color: blue;
}
ul:hover li:hover ~ li{
color: red;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
If you know the exact position an :nth-child()-based exclusion of all following siblings would work.
ul li:not(:nth-child(n+3))
Which would select all lis before the 3rd (e.g. 1st and 2nd). But, in my opinion this looks ugly and has a very tight usecase.
You also could select the nth-child right-to-left:
ul li:nth-child(-n+2)
Which does the same.
No. It is not possible via CSS. It takes the "Cascade" to heart ;-).
However, if you are able to add JavaScript to your page, a little bit of jQuery could get you to your end goal.
You can use jQuery's find to perform a "look-ahead" on your target element/class/id, then backtrack to select your target.
Then you use jQuery to re-write the DOM (CSS) for your element.
Based on this answer by Mike Brant,
the following jQuery snippet could help.
$('p + ul').prev('p')
This first selects all <ul>s that immediately follow a <p>.
Then it "backtracks" to select all the previous <p>s from that set of <ul>s.
Effectively, "previous sibling" has been selected via jQuery.
Now, use the .css function to pass in your CSS new values for that element.
In my case I was looking to find a way to select a DIV with the id #full-width, but ONLY if it had a (indirect) descendant DIV with the class of .companies.
I had control of all the HTML under .companies, but could not alter any of the HTML above it.
And the cascade goes only 1 direction: down.
Thus I could select ALL #full-widths.
Or I could select .companies that only followed a #full-width.
But I could not select only #full-widths that proceeded .companies.
And, again, I was unable to add .companies any higher up in the HTML. That part of the HTML was written externally, and wrapped our code.
But with jQuery, I can select the required #full-widths, then assign the appropriate style:
$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );
This finds all #full-width .companies, and selects just those .companies, similar to how selectors are used to target specific elements in standard in CSS.
Then it uses .parents to "backtrack" and select ALL parents of .companies,
but filters those results to keep only #fill-width elements, so that in the end,
it only selects a #full-width element if it has a .companies class descendant.
Finally, it assigns a new CSS (width) value to the resulting element.
$(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
div {
background-color: lightblue;
width: 120px;
height: 40px;
border: 1px solid gray;
padding: 5px;
}
.wrapper {
background-color: blue;
width: 250px;
height: 165px;
}
.parent {
background-color: green;
width: 200px;
height: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div class="wrapper">
<div class="parent">
"parent" turns red
<div class="change-parent">
descendant: "change-parent"
</div>
</div>
<div class="parent">
"parent" stays green
<div class="nope">
descendant: "nope"
</div>
</div>
</div>
Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>
<b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>
<br>
(reverse cascade, look ahead, parent un-descendant)
</html>
jQuery Reference Docs:
$() or jQuery(): DOM element.
.find: Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
.parents: Get the immediately preceding sibling of each element in the set of matched elements. If a selector is provided, it retrieves the previous sibling only if it matches that selector (filters the results to only include the listed elements/selectors).
.css: Set one or more CSS properties for the set of matched elements.
My requirement was to select currently hovered item's previous and next two siblings with the help of #Quentin 's answer I selected previous siblings.
.child{
width: 25px;
height: 25px;
}
.child:hover {
background:blue;
}
.child:has( + .child:hover) {
background: yellow;
}
.child:has(+ .child + .child:hover){
background:green;
}
.child:hover + .child {
background: red;
}
.child:hover + .child + .child {
background: magenta;
}
<ul class="parent">
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
</ul>
To select all previous siblings
.child {
width: 25px;
height: 25px;
}
.child:hover {
background: blue;
}
.child:has(~ .child:hover) {
background: red;
}
<ul class="parent">
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
<li class="child"></li>
</ul>
Depending on your exact objective, there is a way to achieve the usefulness of a parent selector without using one (even if one were to exist)...
Say we have:
<div>
<ul>
<li><a>Pants</a></li>
<li><a>Socks</a></li>
<ul>
<li><a>White socks</a></li>
<li><a>Blue socks</a></li>
</ul>
</ul>
</div>
What can we do to make the Socks block (including sock colours) stand out visually using spacing?
What would be nice but doesn't exist:
ul li ul:parent {
margin-top: 15px;
margin-bottom: 15px;
}
What does exist:
li > a {
margin-top: 15px;
display: block;
}
li > a:only-child {
margin-top: 0px;
}
This sets all anchor links to have 15px margin on the top and resets it back to 0 for those with no UL elements (or other tags) inside LIs.
/* Add a style to all the children, then undo the style to the target
and sibling children of your target. */
ul>li {
color: red;
}
ul>li.target,
ul>li.target~li {
color: inherit;
}
<ul>
<li>before</li>
<li class="target">target</li>
<li>after</li>
<li>after</li>
</ul>
There is no "previous" sibling selector unfortunately, but you can possibly still get the same effect by using positioning (e.g. float right). It depends on what you are trying to do.
In my case, I wanted a primarily CSS 5-star rating system. I would need to color (or swap the icon of) the previous stars. By floating each element right, I am essentially getting the same effect (the html for the stars thus must be written 'backwards').
I'm using FontAwesome in this example and swapping between the unicodes of fa-star-o and fa-star
http://fortawesome.github.io/Font-Awesome/
CSS:
.fa {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* set all stars to 'empty star' */
.stars-container {
display: inline-block;
}
/* set all stars to 'empty star' */
.stars-container .star {
float: right;
display: inline-block;
padding: 2px;
color: orange;
cursor: pointer;
}
.stars-container .star:before {
content: "\f006"; /* fontAwesome empty star code */
}
/* set hovered star to 'filled star' */
.star:hover:before{
content: "\f005"; /* fontAwesome filled star code */
}
/* set all stars after hovered to'filled star'
** it will appear that it selects all after due to positioning */
.star:hover ~ .star:before {
content: "\f005"; /* fontAwesome filled star code */
}
HTML:
(40)
JSFiddle: http://jsfiddle.net/andrewleyva/88j0105g/
I needed a solution to select the previous sibling tr. I came up with this solution using React and Styled-components. This is not my exact solution (This is from memory, hours later). I know there is a flaw in the setHighlighterRow function.
OnMouseOver a row will set the row index to state, and rerender the previous row with a new background color
class ReactClass extends Component {
constructor() {
this.state = {
highlightRowIndex: null
}
}
setHighlightedRow = (index) => {
const highlightRowIndex = index === null ? null : index - 1;
this.setState({highlightRowIndex});
}
render() {
return (
<Table>
<Tbody>
{arr.map((row, index) => {
const isHighlighted = index === this.state.highlightRowIndex
return {
<Trow
isHighlighted={isHighlighted}
onMouseOver={() => this.setHighlightedRow(index)}
onMouseOut={() => this.setHighlightedRow(null)}
>
...
</Trow>
}
})}
</Tbody>
</Table>
)
}
}
const Trow = styled.tr`
& td {
background-color: ${p => p.isHighlighted ? 'red' : 'white'};
}
&:hover {
background-color: red;
}
`;
There isn't, and there is.
If you must place the label before the input, just place the label after the input and keep both the label & the input inside a div, and style the div as following :
.input-box {
display: flex;
flex-direction: column-reverse;
}
<div class="input-box">
<input
id="email"
class="form-item"
/>
<label for="email" class="form-item-header">
E-Mail*
</label>
</div>
Now you can apply the standard next sibling styling options available in css, and it will appear like you are using a previous sibling styling.
I've found the easiest solution. It might only apply based on what you're doing.
Let's say you want to hover on "sibling_2" to change "sibling_1" in the example below:
<div class='parent'>
<div class='sibling_1'></div>
<div class='sibling_2'></div>
</div>
Since there's no previous element selector you can simply switch 'sibling_1' and 'sibling_2' around and apply so they look the same.
.parent {
display: flex;
flex-direction: row-reverse;
}
Now you can select them like that.
.sibling_1:hover ~ .sibling_2 {
#your CSS
}
You can use :has() as following.
.thePrevious:has(+ .theNextSibling)
I used this for fixing overlapping bootstrap modals as follows. Any previous modals will be hidden if there are multiple.
.modal.show.modal--open:has(~ .modal.show.modal--open){
opacity: 0;
}
There is no such selector, but in the DOM API has a pretty read-only property
Node.previousSibling
I fixed this problem by putting my elements in a flexbox and then using flex-direction: column-reverse.
Then I had to invert my elements in the HTML manually (put them in reverse order), and it looked normal and it worked!
<div style="display: flex; flex-direction: column-reverse">
<a class="element2">Element 2</a>
<a class="element1">Element 1</a>
</div>
...
<style>
.element2:hover + element1 {
...
}
</style>
I had a similar problem and found out that all problem of this nature can be solved as follows:
give all your items a style.
give your selected item a style.
give next items a style using + or ~.
and this way you'll be able to style your current, previous items(all items overridden with current and next items) and your next items.
example:
/* all items (will be styled as previous) */
li {
color: blue;
}
/* the item i want to distinguish */
li.milk {
color: red;
}
/* next items */
li ~ li {
color: green;
}
<ul>
<li>Tea</li>
<li class="milk">Milk</li>
<li>Juice</li>
<li>others</li>
</ul>
Hope it helps someone.
here is the link for a similar question
CSS select all previous siblings for a star rating
So I post my solution using bits of everyones responses and anyone can use it as reference and possibliy recommend improvements.
// Just to check input value
// Consts
const starRadios = document.querySelectorAll('input[name="rating"]');
// EventListeners
starRadios.forEach((radio) => radio.addEventListener('change', getStarRadioValue));
// Get star radio value
function getStarRadioValue(event) {
alert(event.target.value)
// Do something with it
};
.star-rating {
font-size: 1.5rem;
unicode-bidi: bidi-override;
direction: rtl;
text-align: left;
}
.star-rating.editable label:hover {
cursor: pointer;
}
.star-rating.editable .icon-star:hover,
.star-rating.editable .icon-star:hover ~ .icon-star {
background-color: #fb2727 !important;
}
.icon-star {
position: relative;
background-color: #72747d;
width: 32px;
height: 32px;
display: inline-block;
transition: background-color 0.3s ease;
}
.icon-star.filled {
background-color: #fb2727;
}
.icon-star > label {
display: inline-block;
width: 100%;
height: 100%;
left: 0;
top: 0;
position: absolute;
}
.icon-star > label > input[type="radio"] {
position: absolute;
top: 0;
left: 0;
transform: translateY(50%) translateX(50%);
display: none;
}
<div class="star-rating editable">
<span class="icon-star">
<label>
<input type="radio" name="rating" value="5" />
</label>
</span>
<span class="icon-star">
<label>
<input type="radio" name="rating" value="4" />
</label>
</span>
<span class="icon-star">
<label>
<input type="radio" name="rating" value="3" />
</label>
</span>
<span class="icon-star">
<label>
<input type="radio" name="rating" value="2" />
</label>
</span>
<span class="icon-star">
<label>
<input type="radio" name="rating" value="1" />
</label>
</span>
</div>
For my use case was needed to change previous element style on focus and hover only having 2 items in parent element. to do so used :focus-within and :hover pseudo-classes.
like so selecting whenever focus/hover event occurs
.root-element:hover .element-to-style { background-color: red;}
.root-element:focus-within .element-to-style { background-color: green;}
<div class="root-element">
<span class="element-to-style"> TextFocused</span>
<input type="text" placeholder="type To Style"/>
</div>
There is actually no selector that can select the previous sibling in css. But it is possible to use certain tricks.
For example, if you want to change the style of the previous element when you hover over any element, you can use this:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.element:has(+ .next-element:hover){
/* here your style for .element */
}
</style>
</head>
<body>
<div class="container">
<div class="element"></div>
<div class="next-element"></div>
</div>
</body>
</html>
In this situation if you hover over .next-element the style of .element will change as you defined above
I had this same problem, while I was trying to change prepend icon fill color on input focus, my code looked something like this:
<template #append>
<b-input-group-text><strong class="text-danger">!</strong></b-input-group-text>
</template>
<b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />
The problem was that I'm using a vue-bootstrap slot to inject the prepend, so even if i change the location still get rendered after the input
Well my solution was to swipe their location, and add custom prepend and used ~ symbol, as css doesn't support previous sibling.
<div class="form-input-prepend">
<svg-vue icon="common.lock" />
</div>
<b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />
Scss style
.form-control:focus ~ .form-input-prepend {
svg path {
fill: $accent;
}
}
So just try to change its position, and if necessary use css order or position: absolute; to achieve what you want, and to avoid using javascript for this kind of needs.
Though there is no previous CSS selector. I've found a quick and easy method to select one yourself.
Here is the HTML markup:
<div class="parent">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
In your JavaScript simply do:
document.querySelector(".child-2").parentElement.querySelector(".child-1")
This will first select the parent div and later on select the child-1 div from the child-2 div.
If you are using jQuery you can simply do:
$(".child-2").prev()
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 < a.active {
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).
The Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation, but is currently not supported by Firefox.
li:has(> a.active) { /* styles to apply to the li tag */ }
As of 2022, Firefox is the only browser not supporting it by default.
In the meantime, you'll have to resort to JavaScript in Firefox if you need to select a parent element with full cross-browser support.
You can use the :has() CSS pseudo-class
But it has limited browser support (Currently only Chrome / Edge / Safari).
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.
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>
</div>
You can select that span.help 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.
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:
$("a.active").parents('li').css("property", "value");
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(a.active) { 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.
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
Tabindex
Example
.parent:focus-within {
background: hsl(199deg, 65%, 73%);
}
/* demo styles */
body {
margin: 0;
}
.parent {
background: hsl(0, 0%, 80%);
min-height: 100vh;
display: grid;
place-content: center;
}
.child {
background: hsl(0, 0%, 0%);
color: white;
padding: 3rem;
outline: 0;
cursor: pointer;
font: 18px/1.25 sans-serif;
width: 20ch;
}
<div class="parent">
<div class="child" tabindex="1">
Click or Focus on me, my parent will change.
</div>
</div>
There isn't a way to do this in CSS 2. You could add the class to the li and reference the a:
li.active > a {
property: value;
}
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...
}
a.active {
color: ..., background: ...
}
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.
Not in CSS 2 as far as I'm aware. CSS 3 has more robust selectors but is not consistently implemented across all browsers. Even with the improved selectors, I don't believe it will accomplish exactly what you've specified in your example.
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 :(
You might try to use hyperlink as the parent, and then change the inner elements on hover. Like this:
a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}
This way you can change the style in multiple inner tags, based on the rollover of the parent element.
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:
$("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)")
Here's a hack using pointer-events with hover:
<!doctype html>
<html>
<head>
<title></title>
<style>
/* accessory */
.parent {
width: 200px;
height: 200px;
background: gray;
}
.parent,
.selector {
display: flex;
justify-content: center;
align-items: center;
}
.selector {
cursor: pointer;
background: silver;
width: 50%;
height: 50%;
}
</style>
<style>
/* pertinent */
.parent {
background: gray;
pointer-events: none;
}
.parent:hover {
background: fuchsia;
}
.parent
.selector {
pointer-events: auto;
}
</style>
</head>
<body>
<div class="parent">
<div class="selector"></div>
</div>
</body>
</html>
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 'a.active' {
$parent {
background: red;
}
}
So here we've opened an element query on every element a.active, 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.
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.
Just an idea for horizontal menu...
Part of HTML
<div class='list'>
<div class='item'>
<a>Link</a>
</div>
<div class='parent-background'></div>
<!-- submenu takes this place -->
</div>
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
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; }
*/
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 = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {
if(x.parentNode.tagName === 'LI') {
x.parentNode.style.color = 'red'; // Your property: value;
}
});
Or a shorter way if you use jQuery in your application:
$('a.active').parents('li').css('color', 'red'); // Your property: value;
The W3C excluded such a selector because of the huge performance impact it would have on a browser.
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.
a.active h1 {color: blue;}
a.active p {color: green;}
jQuery
$("a.active").parents('li').css("property", "value");
If you want to achieve this using jQuery here is the reference for the jQuery parent selector.
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:
an immediate parent selector < (which enables the opposite selection to >)
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:
.parent {
float: left;
width: 180px;
height: 180px;
margin-right: 12px;
background-color: rgb(191, 191, 191);
}
.child {
width: 90px;
height: 90px;
margin: 45px;
padding-top: 12px;
font-family: sans-serif;
text-align: center;
font-size: 12px;
background-color: rgb(255, 255, 0);
}
.child.using-axe < .parent {
background-color: rgb(255, 0, 0);
}
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child using-axe">Here, the axe parent selector turns the outer square red.</div>
</div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
In the example above < is the immediate parent selector, so
.child.using-axe < .parent
means:
any immediate parent of .child.using-axe which is .parent
You could alternatively use:
.child.using-axe < div
which would mean:
any immediate parent of .child.using-axe which is a div
The CSS parent selector (also know as the :has() selector) has finally landed in Safari TP 137. The feature is currently being implementated in Chrome as well. (MDN Documentation)
Parent selection is done via the pseudo-class :has(). For example, div:has(> .child) will select all <div> elements with a child having a child class.
Other examples:
Selecting direct parent of an element
<div>
<p>Child Element</p>
</div>
div:has(> p)
Selecting all the parents of an element
<div id="grandparent">
<div id="parent">
<div id="child"></div>
<div>
</div>
The following selector will select both grandparent and parent
div:has(.child)
You can also use it for nested selectors and even with other pseudo classes:
div:has(> :nth-child(10))
Other valid CSS operators can be used to customize the query.
Keep an eye on caniuse.com/css-has for browser compatibility.
Updated 2022 CSS Selectors 4
In the CSS Selectors 4 specification, CSS introduces a new selector called :has(), which finally lets us select parents. That means is we’ll be able to target a CSS element that has specific children within it. This is already supported in Safari and is also in Chrome 105. The full support table is shown
here.
Parent Selectors workings
In CSS, if we want to select something, we use selectors that descend the DOM.
For example, selecting a p tag within a div tag looks like this:
div p {
color: red;
}
Until now, couldn’t really select the div tags which had p tags within them, though, and this meant we had to resort to Javascript. The main reason this wasn’t implemented in CSS is that it’s quite an expensive operation to do. CSS is relatively fast to parse, but selecting parent tags requires a relatively significantly larger amount of processing.
Using the :has selector, we can now select div elements which have a p children, or any normal combination of selectors.
For example, selecting a div with a child p now looks like this:
div:has(p) {
color: red;
}
This will make any div with a child p red.
Combining parent selection with other selectors
Just like any other CSS selector, we can combine this for specific circumstances.
For example, if you want to select only div tags which have direct span children:
div:has(> span) {
color: red;
}
As the vocabulary of :has suggested, it is not just limited to parent selection.
For example, below we can select a span which :has a sibling div:
span:has(+ div) {
color: red;
}
Or even, selecting an element which does not have a child, by using the :not() selector.
For example, the following will select any div which does not have a p child:
div:not(:has(p)) {
color: red;
}
Selecting elements that only contain text in CSS
One very common problem in CSS is that the :empty tag does not select elements that contain any text - so sometimes an element can contain one space, and :empty will not apply. The :has selector gives us the power to select elements that only contain text nodes and no other child elements.
Although this is not the perfect solution for simply :empty elements with spaces (as this will select any element with just text and no additional HTML DOM elements) - it does give us the ability to select DOM elements with only text nodes, which was not previously possible. We can achieve this with the following code:
div:not(:has(*)) {
background: green;
}
Any ideas?
CSS4 will be fancy if it adds some hooks into walking backwards. Until 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__checkbox__selection,
.menu__checkbox__style,
.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;
}
/* ▼ - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
content: '\2630';
display: inline-block;
}
*/
/* ▼ - 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:hover,
.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"
name="colorize"
class="menu__checkbox__style"
id="style-default">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-one">
<input type="radio"
name="colorize"
class="menu__checkbox__style"
id="style-two">
<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
</p>
<input type="checkbox"
class="menu__checkbox__selection"
id="trigger-style-menu">
<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>
<li class="menu__option">
<label for="style-one"
class="menu__trigger__style">First Alternative Style</label>
</li>
<li class="menu__option">
<label for="style-two"
class="menu__trigger__style">Second Alternative Style</label>
</li>
</ul>
<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.
</p>
</div>
... 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 pseudo classes, 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.
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.
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');
[].forEach.call(cells, function (el) {
//console.log(el.nodeName)
if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
console.log(el)
};
});
<div>Peter</div>
<div>Jackson link</div>
<div>Philip</div>
<div>Pullman link</div>
Try this...
This solution uses plain CSS2 rules with no Javascript and works in all browsers, old and new. When clicked, the child anchor tag activates its active pseudo-class event. It then simply hides itself, allowing the active event to bubble up to the parent li tag who then restyles himself and reveals his anchor child again with a new style. The child has styled the parent.
Using your example:
<ul>
<li class="listitem">
<a class="link" href="#">This is a Link</a>
</li>
</ul>
Now apply these styles with the active pseudo-class on a to restyle the parent li tag when the link is clicked:
a.link {
display: inline-block;
color: white;
background-color: green;
text-decoration: none;
padding: 5px;
}
li.listitem {
display: inline-block;
margin: 0;
padding: 0;
background-color: transparent;
}
/* When this 'active' pseudo-class event below fires on click, it hides itself,
triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {
display: none;
}
.listitem:active {
background-color: blue;
}
.listitem:active a.link {
display: inline-block;
background-color: transparent;
}
You should see the link with a green background now change to the list item's blue background on click.
turns to
on click.
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" />
</div>
</div>