How do I select the <li>
element that is a direct parent of the anchor element?
In 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).
Any ideas?
转载于:https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector
There is currently no way to select the parent of an element in CSS.
If there was a way to do it, it would be in either of the current CSS selectors specs:
In the meantime, you'll have to resort to JavaScript if you need to select a parent element.
The Selectors Level 4 Working Draft includes a :has()
pseudo-class that works the same as the jQuery implementation. As of 2018, this is still not supported by any browser.
Using :has()
the original question could be solved with this:
li:has(> a.active) { /* styles to apply to the li tag */ }
there isn't a way to do this in css2. you could add the class to the li and reference the a
li.active > a {
property: value;
}
I don’t think you can select the parent in css only.
But as you already seem to have an .active
class, wouldn’t it 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.
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.
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");
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.
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 IE.
The W3C excluded such a selector because of the huge performance impact it would have on a browser.
Try to switch a
to block
display, and then use any style you want. a
element will fill li
element and you will be able to modify it's 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: ...
}
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)")
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.
This article Why we don't have a parent selector explains it in detail.
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.
This is the most discussed aspect of the Selectors Level 4 specification. With this 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 browsers implementation :(
Technically there is no direct way to do this however, you can sort that with either jquery or javascript.
Howeve,r 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 jQuery parent selector
Has somebody suggested something like this? 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
No you cannot select the parent in css only.
But as you already seem to have an .active
class, wouldn´t it 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.
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 IE8 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 IE8, as well as a screenshot in case you don't have IE8 around to test with.
EQCSS also includes meta-selectors $prev
for the element before a selected element, $this
for only those elements that match an element query, and more.
In CSS, we can cascade to the properties down the hierarchy but not in the oppostite direction. To modify the parent style on child event, probably use jQuery.
$el.closest('.parent').css('prop','value');
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:
<
(which enables the opposite selection to >
)^
(which enables the opposite selection to [SPACE]
)axe is presently in a relatively early BETA stage of development.
See a demo here:
http://rounin.co.uk/projects/axe/axe2.html
(compare the two lists on the left styled with standard selectors and the two lists on the right styled with axe selectors)
Short answer is NO, we don't have a parent selector
at this stage in CSS, but if you don't have anyway to swap the elements or classes, 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;
It´s possible with ampersand in SASS:
h3
font-size: 20px
margin-bottom: 10px
.some-parent-selector &
font-size: 24px
margin-bottom: 20px
CSS output:
h3 {
font-size: 20px;
margin-bottom: 10px;
}
.some-parent-selector h3 {
font-size: 24px;
margin-bottom: 20px;
}
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
Example
.click {
cursor: pointer;
}
.color:focus-within .change {
color: red;
}
.color:focus-within p {
outline: 0;
}
<div class="color">
<p class="change" tabindex="0">
I will change color
</p>
<p class="click" tabindex="1">
Click me
</p>
</div>
</div>
At least up to and including CSS3 you cannot select like that. But it can be done pretty easily nowadays in JS, 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><a href="#">Jackson link</a></div>
<div>Philip</div>
<div><a href="#">Pullman link</a></div>
</div>
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>
</div>