I am trying to change the text colour of .foo when the user hovers over .bar and I am unsure how to do this with only CSS. I have tried using the CSS preceding element selector ~ but that did not work.
http://jsfiddle.net/847E2/
<div>
<p class="foo">Foo</p>
<ul class="bar"><li>Bar<li></ul>
</div>
.bar:hover~.foo {
color: red;
}
EDIT - My requirements have changed. I updated my HTML structure to make the .bar a <ul>
The sibling selector ~ doesn't select elements preceding it, just elements succeeding it. Thus, when hovering over the element .bar, the element .foo cannot be selected, as it is preceding .bar.
You could do something like this instead:
jsFiddle example
div:hover :not(:hover) {
color: red;
}
Basically, this is setting the color of the child elements to color:red when hovering over the parent, div. However, it will not be applied on :hover of the element you are on. This makes it seem as though the color is changing when you hover over the sibling element.
Here's a way to do it with CSS (no CSS3 needed):
div:hover p{
color: red;
}
.foo:hover{
color: black;
}
div:hover p.bar{
color: black;
}
jsFiddle example
The + selector is an adjacent sibling combinator selector allows you to select an element that is directly after another specific element.
It doesn't matter if you use any element if have .bar class name.
NOTE: There is no "previous sibling" selector, that's why i change the elements order in the DOM.
.bar:hover + .foo {
color: red;
}
Demo http://jsfiddle.net/847E2/11/
Also can see: http://css-tricks.com/child-and-sibling-selectors/
Is there a "previous sibling" CSS selector?
Related
Why does the :not selector not work at all in this case:
a {
color:red;
}
div a:not(.special a) {
color: green;
}
In, for example:
<div>
<span>hellolink</span>
</div>
<div class="special">
<span>hellolink</span>
</div>
<p>
something else
</p>
Demo: https://jsfiddle.net/eguecrvz/
:not() currently doesn't allow combinators or any more than one simple selector (such as .special or a) as an argument. A future specification will expand :not() to accept any number of complex selectors, and once browsers support it your selector div a:not(.special a) will work exactly as intended.
In the meantime, it is not possible to write a selector for "an a element that does not have a .special ancestor element." You will need to override with an additional .special a selector in your rule that applies to a elements in general:
a, .special a {
color:red;
}
div a {
color: green;
}
The additional specificity of .special a will ensure that it overrides div a, but if specificity is a problem you will need to rearrange your rulesets.
special is class of div not anchor.
Change css like:
div:not(.special) a{
color: green;
}
Fiddle
Edit:
If you want all link green except .special the do like:
a {
color:green;
}
.special a{
color: red;
}
Updated Fiddle
Why doesn't css :not work in some cases?
div a:not(.special a) {
color: green
}
Because the negation pseudo-class (:not) only takes a simple selector as an argument.
Your argument (.special a) represents a descendant selector which does not qualify.
6.6.7. The negation
pseudo-class
The negation pseudo-class, :not(X), is a functional notation taking
a simple selector (excluding the negation pseudo-class itself) as an
argument. It represents an element that is not represented by its
argument.
What is a simple selector?
4. Selector syntax
A simple selector is either a type selector, universal selector,
attribute selector, class selector, ID selector, or pseudo-class.
I know that with pure CSS it's impossible to select previous siblings of the element. But I try to fool browser with a complex selector.
Please see this jsFiddle. It contains several CSS rules that work fine except 2 of them:
//set border color to white for all elements before .selected and .selected itself
div:not(.selected ~ div) {
border-color: #fff;
}
//set border color to green for the element previous to .selected
div:not(.selected ~ div):nth-last-child(2) {
border-color: #0f0;
}
But seems that inside :not() sibling selector ~ doesn't work.
So there're 2 questions:
Is it expected that ~ doesn't work inside :not()?
Is there any work-around for such case?
EDIT:
The final idea is to make a nice hover effect with pure CSS like:
The hovered image is simply scaled, image to right of it could be found and styled easily but the left one... The example with divs is just an example.
:not() pseudo-class could not contain sibling selector.
http://dev.w3.org/csswg/selectors3/#negation
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument.
http://dev.w3.org/csswg/selectors3/#simple-selectors-dfn
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
If you want to :
set border color to white for all elements before .selected and
.selected itself
I would suggest to default the border color to white and change it after .selected :
div {
display: inline-block;
border: 1px solid #fff;
width: 30px;
}
div.selected ~ div {
border-color: #000;
}
<div>A</div>
<div>B</div>
<div class="selected">C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
For the second rule :
set border color to green for the element previous to .selected
If you know wich one will be selected in advance, you can target the element before with nth-child() otherwise you will need some JS to select it.
An other approach if the .selected class is dynamicaly added would be to use the same mechanism (PHP, JS or other) to give a class to the privious element at the same time and apply CSS to that class.
It is possible since CSS Level 4.
https://www.w3.org/TR/selectors-4/
The negation pseudo-class, :not(), is a functional pseudo-class taking a selector list as an argument.
Also it is changed from :not( <selector># ) to :not( <complex-selector-list> ) in https://developer.mozilla.org/en-US/docs/Web/CSS/:not#syntax in November 2018.
See browser compatibility for "Selector list argument" in https://developer.mozilla.org/en-US/docs/Web/CSS/:not#browser_compatibility.
I would like to select the first div called "aProduct" but I'm a bit confused on how to do this. I already tried this:
<div id="kasticketProducts">
<div class="aProductHeader"></div>
<div class="aProduct"></div>
<div class="aProductHeader"></div>
<div class="aProduct"></div>
</div>
This is my current CSS:
#kasticketProducts:first-child .aProduct {
margin-top: 30px;
background: red;
}
#kasticketProducts:first-child .aProduct
Using above css means first it'll search for id with kasticketproducts in that first-child, here first child refer to aProductHeader from here you are trying to search aProduct but it is not there.
Actually from DOM hierarchy aProduct class div is at second child this will be referred in css as nth-child(2) here and no need of again .aProduct .So the final solution for this is write as #kasticketProducts div:nth-child(2)
First, whats the difference?
From MDN :
:first-child()
The :first-child CSS pseudo-class represents any element that is the first child element of its parent.
:first-of-type()
The :first-of-type CSS pseudo-class represents the first sibling of its type in the list of children of its parent element.
So inshort, :first-child() is somewhat a loose pseudo selector compared to :first-of-type()
Unfortunately :first-child or :first-of-type doesn't respect classes or ids, they are only concerned with the DOM elements. So if you do something like, will fail
#kasticketproducts div.aProduct:first-of-type {
color: red;
}
So in this case the best you can do with CSS is use :nth-of-type() with 2 as a value, now obviously it will fail if your element doesn't have a class of aProduct
#kasticketproducts div:nth-of-type(2) {
color: red;
}
Demo
OR
you can use adjacent selector with :first-of-type()
#kasticketproducts div:first-of-type + div {
color: red;
}
Demo
Second solution is MORE COMPATIBLE as far as IE is concerned
DEMO
Code is not working because aProductHeader class is before first occurrence of aProduct class.
See demo.
You can't target the first element of a class, but you can target the elements that come after, so you can set the styles on all the aProduct elements and then override it on all aProduct that comes after the first one using the ~ opreator:
#kasticketproducts .aProduct {
margin-top: 30px;
background: red;
}
#kasticketproducts .aProduct ~ .aProduct {
margin-top: 0;
background: none;
}
Demo: http://jsfiddle.net/a9W5T/
You can use
:first-child, :nth-of-type(1), :first-of-type or :nth-child(1n)
And why your code donst work, is because you use:
#kasticketProducts:first-child .aProduct
this will take the first element #kasticketProducts, use this instead: #kasticketProducts .aProduct:nth-child(2) {
color: red;
} <-- This will take the first element .aProduct inside your ID element
Another solution would be to style .aProduct, and then override the style for any succeeding occurrences of .aProduct using the general sibling combinator:
#kasticketProducts .aProduct {
// effectively becomes the style for the first occurrence of .aProduct
}
#kasticketProducts .aProduct ~ .aProduct {
// overrides the style set above for all occurrences of .aProduct,
// apart from the first
}
The biggest advantage of this approach is that it doesn't rely on the structure of the markup.
General sibling selectors on MDN
Here's an example
Check the #id, it's case sensitive
Also, be careful with quotes, you are not closing them.
<div id="kasticketProducts">
<div class="aProductHeader">aaa</div>
<div class="aProduct">aaa</div>
<div class="aProductHeader">aaaa</div>
<div class="aProduct">aaa</div>
For the first .aProduct get selected:
#kasticketProducts .aProduct:nth-child(2) {
/* your styles */
}
Sorry for that, thought was for getting the first kasticketProduct. Apologizes.
Is it possible to style another element on :focus of a specific element?
Something like:
input:focus #header {
display: none;
}
I tried doing that but it didn't work.
Yes,it is possible if element is a sibling or a child to the :focus element. If it is not your case (affect whatever you want) than you should use javascript.
.input:focus #header
That is applying selecting all #header where they are a descendant of input
If its a sibling so you want, use the next sibling selector +:
input:focus + #header
For more information on child/sibling combinators
you can also use 'preceded by' selector -> https://www.w3schools.com/cssref/css_selectors.asp
HTML:
<button>button</button>
<div class="div1">div1</div>
CSS:
button:hover ~ .div1 {
color: red;
}
So you hover over the button BUT the div1 element gets styled.
Just make sure that the BUTTON element is first and the element you are styling is SECOND.
I want to change another element property on hover of a element. So far I've I came up with the following CSS:
#test3:hover #test4
{
background-color: red;
}
<div id="test3">three</div>
<div id="test4">four</div>
However, this is not working. Is this possible at all? What would you suggest?
#test3:hover #test4
This means, target an element test4 that is a child of test3. You want the + sibling selector instead:
#test3:hover + #test4
{
background-color: red;
}
Browser compatibility table