CSS: Possible to select a certain child plus the immediate following sibling? - css

I'm currently doing this using Javascript, however, I was wondering if it's possible to select a certain child of an unordered-list and then its immediate sibling, using CSS.
Example with 4 list-items:
ul.tab li:hover + (the next sibling that follows the current hovered one) {
}

You want the adjacent sibling selector for which you amusingly basically have the syntax already.
Be advised: :hover is specifically a x-browser problem in Safari though.

Related

CSS - :target ~

That´s my html code:
test
<ul id="anchor"></ul>
Now I want to style my target, which isn´t a problem.
#anchor:target
{
}
But I want to select the sibling of the target (a).
#anchor:target ~ a{
background: blue;
}
It´s not working. How to select the sibling of the target?
Currently, there is no way to style the previous siblings with CSS. To achieve this, you'll have to use javascript.
You can get the next sibling with + or all <a>s after your <ul> with ~:
#anchor:target + a {
/*
<ul></ul>
<a>will get this one</a>
<a>but not this one</a>
*/
}
#anchor:target ~ a {
/*
<ul></ul>
<a>will get this one</a>
<a>and this one too!</a>
*/
}
In CSS there is no "previous" sibling selector (in CSS2 or CSS3).
The "Selectors Level 4" draft introduces the ! selector, which if I understand it correctly, allows for previous sibling selection.
https://drafts.csswg.org/selectors-4/#subject
However, this is still in draft form, and is far from being supported in all the major browsers.
Sorry, but it's not possible with the current CSS spec.
The only way to really achieve this would be to use JavaScript, or to change the order of your markup.
Currently, you cannot get previous siblings. But you can select a element with specific attribute like this:
a[href="#anchor"] {
color: #f00;
}
test
<ul id="anchor"></ul>
as per my previous answer, this isn't possible in the way you've written due to limitations in CSS.
However, you could always match the itself?
a[target|="#"] {
}
This would select all <a> tags within your document that point to local anchors.

It is possible to trigger a non-sibling element with my ID selector using only CSS? [duplicate]

This question already has answers here:
How do I select an element based on the state of another element in the page with CSS?
(3 answers)
Closed 8 years ago.
This example shows in detail... The problem starts with:
.h:hover { background:red }
.h:hover ~ td { background:blue }
That works fine: the :hover event selector triggers the following-sibling td element. So, we can say that the ".h:hover triggers ~ td"... But, if the td element has a backward occurrence, there is no selection.
PS: note that the rolspan in the example causes a "layout with a td following-sibling" where structure have a td that is not following.
The only possibility is the #id selector. So, why does CSS not offer some operator or construction to use #id in that constraint?
SUB-QUESTION#1: is there any pure CSS solution?
(edit) Thanks #TylerH to show that sub-question#1 is not a duplicate (!).
The point here is the #id selector in a trigger-event context.
Why CSS3 or CSS4 or "?" standards are not using #id for this kind of application. Are there some standard about CSS events and a better control for manage them?
We know that there is no "previous sibling" selector, and this is an understandable problem with parse algorthims. But "find #id" algorithm (no matter if next or previous!) is so simple and so fast, there are no "parse problem" to adopt #id in a kind of "trigger selector".
SUB-QUESTION#2: there are a standardization iniciative (at CSS WG?) to do some workaround to the problem, using #id as triggered selector?
PS
The HTML label tag and for attibute deal with similar problem. A <label for="for"> not need Javascript to triggers (by click event) its correspondent <input type="checkbox" id="for"> checked... So, we can imagine an on-mouse-over correspondent event triggering in the same way,
label#from1:hover <OPERATOR> #for1 { ...do something... }
at a typical HTML form like this,
<div id="for1">
<input type="checkbox" id="mycheck"/>
<span></span>
</div><!-- tag input BEFORE tag label-->
<label id="from1" for="mycheck">Label for my styled "checkbox"</label>
The ~ selector is called the "general sibling" selector. This means it can only be used to select siblings of the appropriate element. In your case, the #c21 element does not have any siblings (brothers or sisters).
What you are asking for cannot be done with pure CSS, because it requires a parent selector (something like :has() from CSS Selectors Level 4). By "parent selector", I mean the ability to move backward up the DOM to an ancestor element, so that you can then move to the ancestor's sibling, and then to the ancestor's sibling's child element.
Think of it this way: the working selector is a boy selecting his sister. That is OK in CSS-land. However, the not-working selector is a boy trying to select his cousin. This is not OK in CSS-land, because it requires a parent selector. The boy would need to first select his parent, then his parent's brother, and then this parent's brother's son.
The fact that it is an ID rather than a class is irrelevant.

CSS selector for "having previous sibling of"

I have an element with a ng-list attribute. The very next sibling to this element is an <ol>. I want to write a CSS selector that selects this <ol>.
In other words, I want to write CSS that applies to an <ol> when the <ol> has an immediate previous sibling of [ng-list].
Possible?
It's called an adjacent sibling selector.
For starters, I would never ever write this CSS selector, you're tying to an angular attribute, it makes no sense. You should just give you OL a class.
[ng-list] + ol { /* rules here */ }
CSS doesn't have a 'previous element' selector yet.
Since you want to select the ol that immediately follows another element, use +, it will select only the specified element that immediately follows the former specified element.
In your case
[ng-list] + ol {
/* css rules */
}
Ref: 5.7 Adjacent sibling selectors

Opposite of adjacent sibling selector?

Please check this fiddle - http://jsfiddle.net/vfMsS/. I need to write selectors which select the element after the "active" element and the element before it. The "before" part doesn't seem to work. How to select the element before the a.active?
Like BoltClock said, there is no way to due this in current day browsers.
However, I believe it is possible in CSS.
The CSS Selectors level 4 syntax (specifically see this) with the syntax E! + F for "An element E preceding an element F".
So in your case the syntax would be a! + a.active meaning "An element with tag a preceding an element with tag a and class active". As of today, this is not yet implemented in any layout engine
The adjacent sibling selector only looks forward, not backward. There is no - combinator for previous adjacent siblings.
If you simply need to select anything that isn't .active in the same parent, and you don't mind slightly reduced browser support, you can use :not() instead. If you need to specify a different style for the one that comes after .active, you need to override:
a:not(.active) { background:red }
a.active + a { background:yellow }
Again, this assumes they always share the same parent.
jsFiddle preview
I was looking for the same solution of targeting the elements behind the .activelink
I set a default style for any element before the one .active then I selected all after that one with the sibling selector.
a.active { background: #ccc;}
a.active ~ * { background: yellow }
a { background: red }
Demo: https://codepen.io/ramiro-ruiz/pen/gBOPQL
That worked for me, hope it helps.
Why don't you try using a sibling combinator?
a.active ~ a { background:red }
http://jsfiddle.net/VixedS/6x7d9vm7/
I have to say, this is an issue I had for a while, and one of the things I didn't like much ended up resolving this issue... float: right.
In my case, it was the input[type='radio'] + label element, and since CSS flows forward and not backwards, ~ input[type='radio'] + label would choose all the siblings after the element that was checked.
Since, float: right is responsible for taking "A, B, C" and positioning them as "C, B, A" - I changed the order of radio elements from 1-6 to 6-1 in the HTML, and made them float: right with CSS.
What this did was reverse them back into the order of 1-6 when rendered to the browser.
Now, when I used ~ input[type='radio'] + label, it still defined the styles the same way (which in my case, was the color of the label), however, the siblings being styled were now - visually - the preceding ones.
This thread is over a year old, but if anyone needs an example, I'll create and post a pen if asked.

Combining two selectors in CSS3

Is there anyway to combine two selectors? such as:
#div:hover:not(.class)
Edit:
I understand this work as I wrote. However, how can I achieve a "hover" effect for a "LI" element , but exclude the hover effect when the mouse is over a certain "DIV' inside the LI?
E.G.
<li>Hello <div id="#no-hover">Bye</div> </li>
I would like to get a hover effect for the li:
li:hover{ text-color:#CCC; }
but somehow exclude the hover effect when the mouse is over the #no-hover div.
Any ideas?
Based on your question edit, to maximize browser compatibility (I mean, why not if you can?) you can get away with not using CSS3 selectors at all. Try this, assuming black is the default text color:
li, li:hover div#no-hover {
color: #000;
}
li:hover {
color: #ccc;
}
Although you may want to use a class instead of an ID if you want to affect multiple elements with a no-hover classification. In which case you would do this instead for your first rule:
li, li:hover div.no-hover {
Either way, since selecting a descendant with its ancestor is more specific than selecting just the ancestor, assuming the same combinators on the ancestor it'll override the second rule even though that one comes later.
Update:
If you only want to have the hover effect not applying to Bye, then you can just create an extra hover rule for that and set the color explicitly (as other answers showed).
If the hover effect should not apply to the whole li element, then I think there is no way to do it. You needed some kind of parent selector, which does not exist in CSS.
Yes and it is fairly easy to try: http://jsfiddle.net/5vaUW/
(probably only works if your browser supports CSS3)
You might want to read more about CSS3 selectors, where you can find this:
A selector is a chain of one or more sequences of simple selectors separated by combinators. One pseudo-element may be appended to the last sequence of simple selectors in a selector.
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
In css2, would be:
li:hover{
color:#CCC;
}
li:hover div{
color: #000;
}
For CSS3, I agree with Felix Kling.

Resources