I have four divs, and i want to change their width and height on hover so the one you are hovering over expands and all others shrink for how much hovered one expanded. I managed to get it working when i hover over first div, but when i try to do the same with other three nothing happens.
My HTML:
<div id="main">
<div id="mainOne">
<h3>text</h3>
</div>
<div id="mainTwo">
<h3>text2</h3>
</div>
<div id="mainThree">
<h3>text3</h3>
</div>
<div id="mainFour">
<h3>text4</h3>
</div>
</div>
My CSS:
/* HOVER 1 */
#mainOne:hover{
width:748px;
height:600px;
}
#mainOne:hover + #mainTwo{
width:248px;
height: 600px;
}
#mainOne:hover ~ #mainThree{
height:200px;
}
#mainOne:hover ~ #mainFour{
height:200px;
}
/* END HOVER 1 */
/* HOVER 2 */
#mainTwo:hover{
width:748px;
height:600px;
}
#mainTwo:hover + #mainOne{
width:248px;
height: 600px;
}
#mainTwo:hover + #mainThree{
height:200px;
}
#mainTwo:hover ~ #mainFour{
height:200px;
}
/* END HOVER 2 */
So when i hover over mainOne, everything changes, but when i hover over mainTwo just mainTwo changes and messes up everything else. What am i doing wrong?
Thanks.
CSS can only (currently) target elements that appear later in the DOM, therefore #mainTwo + #mainThree will work, but #mainTwo + #mainOne cannot.
To target previous siblings you'd have to wrap the siblings within another, parent, element and then style the previous siblings based on the hover of that parent.
div > div {
border: 1px solid #000;
padding: 0.5em 1em;
width: 80%;
margin: 0 auto;
color: #f00;
}
#main:hover > div {
width: 50%;
}
#main:hover > div:hover ~ div {
width: 50%;
}
#main:hover > div:hover {
width: 80%;
}
JS fiddle proof-of-concept
All your mainTwo rules with :hover use the adjacent sibling combinator.
Only #mainTwo + #mainThree can match as neither #mainOne or #mainFour are the next sibling to #mainTwo.
If you used the general sibling combinator (~) then you could match #mainFour too.
Since #mainOne precedes #mainTwo, you can't match it with a rule that depends on the existence of #mainTwo.
Related
In my HTML below, when I hover on the <a> element I want to change the colour of the <h1> element using only CSS. Is there a way to achieve this?
<h1>Heading</h1>
<a class="button" href="#"></a>
What if I wrap a div around it with an id in it?
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#"></a>
</div>
Will this help?
You can make a sibling that follows an element change when that element is hovered, for example you can change the color of your a link when the h1 is hovered, but you can't affect a previous sibling in the same way.
h1 {
color: #4fa04f;
}
h1 + a {
color: #a04f4f;
}
h1:hover + a {
color: #4f4fd0;
}
a:hover + h1 {
background-color: #444;
}
<h1>Heading</h1>
<a class="button" href="#">The "Button"</a>
<h1>Another Heading</h1>
We set the color of an H1 to a greenish hue, and the color of an A that is a sibling of an H1 to reddish (first 2 rules). The third rule does what I describe -- changes the A color when the H1 is hovered.
But notice the fourth rule a:hover + h1 only changes the background color of the H1 that follows the anchor, but not the one that precedes it.
This is based on the DOM order, and it's possible to change the display order of elements, so even though you can't change the previous element, you could make that element appear to be after the other element to get the desired effect.
Note that doing this could affect accessibility, since screen readers will generally traverse items in DOM order, which may not be the same as the visual order.
Edit
This should now be possible using the has selector, in the browsers that support it.
See the comments in the CSS below.
I will edit again in the future; currently my Chrome and Safari browsers are not yet at versions that support it.
h1 {
color: #4fa04f;
}
h1 + a {
color: #a04f4f;
}
h1:hover + a {
color: #4f4fd0;
}
a:hover + h1 {
background-color: #444;
}
/* Select an H1 heading that has an <a>nchor as a sibling */
h1:has(+ a) {
background-color: cyan;
}
/* Select an H1 heading that has a currently-hovered <a>nchor as a sibling */
h1:has(+ a:hover) {
background-color: yellow;
}
<h1>Heading</h1>
<a class="button" href="#">The "Button"</a>
<h1>Another Heading</h1>
There is no CSS selector that can do this (in CSS3, even). Elements, in CSS, are never aware of their parent, so you cannot do a:parent h1 (for example). Nor are they aware of their siblings (in most cases), so you cannot do #container a:hover { /* do something with sibling h1 */ }. Basically, CSS properties cannot modify anything but elements and their children (they cannot access parents or siblings).
You could contain the h1 within the a, but this would make your h1 hoverable as well.
You will only be able to achieve this using JavaScript (jsFiddle proof-of-concept). This would look something like:
$("a.button").hover(function() {
$(this).siblings("h1").addClass("your_color_class");
}, function() {
$(this).siblings("h1").removeClass("your_color_class");
});
#banner:hover h1 {
color: red;
}
#banner h1:hover {
color: black;
}
a {
position: absolute;
}
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#">link</a>
</div>
The Fiddle: http://jsfiddle.net/joplomacedo/77mqZ/
The a element is absolutely positioned. Might not be perfect for your exisiting structure. Let me know, I might find a workaround.
It is indeed possible to achieve this with only a few lines of CSS and some basic Flexbox understanding.
As Stephen P said in his answer, the adjacent sibling combinator does select immediately following siblings. To achieve what the OP asked, you could use two flex approaches:
Approach 1 (using "flex-flow" shorthand property)
.flex-parent {
display: flex;
flex-flow: column-reverse wrap
}
.flex-child-1:hover + .flex-child-2 {
color: #FF3333;
}
<div class="flex-parent">
<a class="flex-child-1">Hover me</a>
<h1 class="flex-child-2">I am changing color</h1>
</div>
Approach 2 (using "order" property and multiple children)
.flex-parent {
display: flex;
flex-direction: column;
}
.flex-child-1 {
order: 2;
}
.flex-child-2 {
order: 1;
}
.flex-child-3 {
order: 3;
}
.flex-child-1:hover+.flex-child-2 {
color: #FF3333;
}
<div class="flex-parent">
<h1 class="flex-child-3">I am not changing color</h1>
<a class="flex-child-1">Hover me</a>
<h1 class="flex-child-2">I am changing color</h1>
</div>
Bonus:
CodePen Bonus
http://plnkr.co/edit/j5kGIav1E1VMf87t9zjK?p=preview
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<style>
ul:hover > li
{
opacity: 0.5;
}
ul:hover li:hover
{
opacity: 1;
}
</style>
</head>
<body>
<h1>Hello Plunker!</h1>
<ul>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
</ul>
</body>
</html>
here is an example how it can be done in pure css , hope it helps somebody
Try this one-line pure CSS solution:
.parent:hover .child:not(:hover) {
/* this style affects all the children *except* the one you're hovering over */
color: red;
}
More info here: https://codyhouse.co/nuggets/styling-siblings-on-hover
Change the H1 tag into a link, style it the same as the normal text maybe?
And then use this,
a:link {color:#FF0000;}
a:hover {color:#FF00FF;}
And it should work when you hover :) you can also make it specific by containing it in a div and then targeting it like this:
.exampledivname a:link {color:#FF0000;}
.exampledivname a:hover {color:#FF00FF;}
This should help.
Someone helped me with this so I thought I would share here as well.
In your first example that is indeed impossible with pure CSS. However, when you wrap it with a parent container you then have the ability to do a bunch of stuff with hovering children.
#banner:hover>h1{
color:red;
}
h1:hover{
color:black !important;
}
#banner{
display:inline-block;
}
.button{
display:inline-block;
font-size:24px;
width:100%;
border:1px solid black;
text-align:center;
}
h1{
padding:0;
margin:0;
}
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#">Button!</a>
</div>
The parent just controls the children who aren't currently being hovered. You then can set hover states for individual elements and classes to make sibling selection possible without JS.
Here is a more advanced example of this in action
https://codepen.io/levyA/pen/gOrdaLJ
For set styles in sibling elements you can use ~ character
in first case when h1 hovered set color for a tag
and in second case when a is hovered, change background color of h1 section
h1:hover ~ a {
color: #e34423;
}
a:hover ~ h1 {
background-color: #eee;
}
This might work, I've recently used this idea to stop sibling elements in an animation.
h1 { color: inherit; }
#banner:hover { color: your choice; }
I want to style an object 2 when the user hovers object 1 in css. For Example:
<style>
.object1:Hover then style object2{
Styling of object2 Goes Here
}
</style>
how can i do that
You can do this in several ways, as long as the html element 1 and 2 fulfill some conditions:
Object 1 has to come before Object 2 in your markup (as you
cannot go "up" or "back" in css selectors).
Object 2 has to be reachable by a css selector from Object 1's perspective (again, you cannot go "up" or "back" in css
selectors), that means that Object 2 cannot for example be in a
parent context of Object 1 (which would also violate 1.).
Examples for such selectors:
1. Child selector
.object1:hover .object2 { your css rules here }
works for an html structure, where .object2 is a child element of .object1:
<div class="object1">
<div class="object2">Some content</div>
</div>
2. Adjacent sibling selector
.object1:hover + .object2 { your css rules here }
works for the (one!) immmediately following sibling .object2:
<div class="object1"></div
<div class="object2">This will be affected.</div>
<div class="object2">This will NOT be affected.</div>
3. All siblings selector
.object1:hover ~ .object2 { your css rules here }
will apply your style for all (possibly many!) sibling .object2 (but just as + NOT for child .object2):
<div class="object1">
<div class="object2">This will NOT be affected.</div>
</div>
<div class="object2">This will be affected.</div>
<someElementWhichisNotAffected></someElementWhichisNotAffected>
<p class="object2">This will be affected.</p>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
div{
width: 200px;
height: 200px;
border: 2px solid #ccc;
margin: 10px auto;
}
.div1:hover{
border: 2px solid #000;
}
.div1:hover ~ .div2{
background: #f00;
}
<div class="div1"></div>
<div class="div2"></div>
I'm trying to sibling-select images. There's a sequence of images that are wrapped with links and I want to select all but the first one.
img {
max-width: 50px;
}
.content img {
max-width: 400px;
}
img.a ~ img.a {
border: 1px #333 solid;
}
<div class="content">
<a href="/">
<img class="a b c" src="https://upload.wikimedia.org/wikipedia/commons/6/6d/Astrodon1DB.jpg">
</a>
<a href="/">
<img class="a b c" src="https://upload.wikimedia.org/wikipedia/commons/2/27/Nipponosaurus_dinosaur.png">
</a>
<a href="/">
<img class="a b c" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Macronaria_scrubbed_enh.jpg/800px-Macronaria_scrubbed_enh.jpg">
</a>
</div>
Here's a fiddle: http://fiddle.jshell.net/efsev59z/
Why doesn't img.a ~ img.a select all images with class "a" that follows an image with class "a"? From my understanding they're both children of a common element, .content. What's wrong, and how do I make it happen?
To be considered siblings, the elements need to be children of the same immediate parent (not just a common ancestor, since all DOM elements share body as an ancestor for example). Consider something like this:
a ~ a > img.a {
/* styles */
}
sibling selectors only apply to siblings. Each one of those images have their own parents. They are cousins, rather than siblings.
A different approach is to apply the border to all images but then override it for the first image. You can use the :first-child selector to get the first anchor and target the image within it.
img {
max-width: 50px;
}
.content img {
max-width: 400px;
}
img.a {
border: 1px #333 solid;
}
.content a:first-child img {
border:none;
}
http://fiddle.jshell.net/efsev59z/4/
I follow this example
https://stackoverflow.com/a/19122409/2761794
Please view this jsfiddle
http://jsfiddle.net/rflfn/pZr3c/
HTML:
<!-- This Works -->
<div class='container'>Mouse Over Here!</div>
<div class='test'>
<div class='text'></div>
</div>
<br />
<!-- This not Work -->
<div class="container1">
<div class='container2'>Mouse Over Here2!</div>
</div>
<div class='test2'>
<div class='text2'></div>
</div>
CSS:
/* This Works */
.test .text:before{
content: 'Text2 Normal';
color: red;
}
.container:hover ~ .test .text:before{
content: 'Text2 Hover';
color: green;
}
/* -------- */
.test2 .text2:before{
content: 'Text2 Normal';
color: red;
}
/* This not Work */
.container1 .container2:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}
/* This not Works too */
/*.container2:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}*/
First Example works perfecly, but second example dont work. I need use this with div inside div, but works only if div the div has not within another div. What's wrong? I would like if possible to use only css to do this.
.container1 .container2:hover ~ .test2 .text2:before
It doesn't work because .container2 isn't a sibling element of .test2. Its parent, .container1, is a sibling therefore the following would work:
(~ is a general sibling combinator - it only looks at sibling elements.)
.container1:hover ~ .test2 .text2:before{
content: 'Text2 Hover';
color: green;
}
I'm afraid what you're trying to do isn't possible in pure CSS since you can't transverse the DOM and there are no parent selectors present. You would need JS to do that.
In my HTML below, when I hover on the <a> element I want to change the colour of the <h1> element using only CSS. Is there a way to achieve this?
<h1>Heading</h1>
<a class="button" href="#"></a>
What if I wrap a div around it with an id in it?
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#"></a>
</div>
Will this help?
You can make a sibling that follows an element change when that element is hovered, for example you can change the color of your a link when the h1 is hovered, but you can't affect a previous sibling in the same way.
h1 {
color: #4fa04f;
}
h1 + a {
color: #a04f4f;
}
h1:hover + a {
color: #4f4fd0;
}
a:hover + h1 {
background-color: #444;
}
<h1>Heading</h1>
<a class="button" href="#">The "Button"</a>
<h1>Another Heading</h1>
We set the color of an H1 to a greenish hue, and the color of an A that is a sibling of an H1 to reddish (first 2 rules). The third rule does what I describe -- changes the A color when the H1 is hovered.
But notice the fourth rule a:hover + h1 only changes the background color of the H1 that follows the anchor, but not the one that precedes it.
This is based on the DOM order, and it's possible to change the display order of elements, so even though you can't change the previous element, you could make that element appear to be after the other element to get the desired effect.
Note that doing this could affect accessibility, since screen readers will generally traverse items in DOM order, which may not be the same as the visual order.
Edit
This should now be possible using the has selector, in the browsers that support it.
See the comments in the CSS below.
I will edit again in the future; currently my Chrome and Safari browsers are not yet at versions that support it.
h1 {
color: #4fa04f;
}
h1 + a {
color: #a04f4f;
}
h1:hover + a {
color: #4f4fd0;
}
a:hover + h1 {
background-color: #444;
}
/* Select an H1 heading that has an <a>nchor as a sibling */
h1:has(+ a) {
background-color: cyan;
}
/* Select an H1 heading that has a currently-hovered <a>nchor as a sibling */
h1:has(+ a:hover) {
background-color: yellow;
}
<h1>Heading</h1>
<a class="button" href="#">The "Button"</a>
<h1>Another Heading</h1>
There is no CSS selector that can do this (in CSS3, even). Elements, in CSS, are never aware of their parent, so you cannot do a:parent h1 (for example). Nor are they aware of their siblings (in most cases), so you cannot do #container a:hover { /* do something with sibling h1 */ }. Basically, CSS properties cannot modify anything but elements and their children (they cannot access parents or siblings).
You could contain the h1 within the a, but this would make your h1 hoverable as well.
You will only be able to achieve this using JavaScript (jsFiddle proof-of-concept). This would look something like:
$("a.button").hover(function() {
$(this).siblings("h1").addClass("your_color_class");
}, function() {
$(this).siblings("h1").removeClass("your_color_class");
});
#banner:hover h1 {
color: red;
}
#banner h1:hover {
color: black;
}
a {
position: absolute;
}
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#">link</a>
</div>
The Fiddle: http://jsfiddle.net/joplomacedo/77mqZ/
The a element is absolutely positioned. Might not be perfect for your exisiting structure. Let me know, I might find a workaround.
It is indeed possible to achieve this with only a few lines of CSS and some basic Flexbox understanding.
As Stephen P said in his answer, the adjacent sibling combinator does select immediately following siblings. To achieve what the OP asked, you could use two flex approaches:
Approach 1 (using "flex-flow" shorthand property)
.flex-parent {
display: flex;
flex-flow: column-reverse wrap
}
.flex-child-1:hover + .flex-child-2 {
color: #FF3333;
}
<div class="flex-parent">
<a class="flex-child-1">Hover me</a>
<h1 class="flex-child-2">I am changing color</h1>
</div>
Approach 2 (using "order" property and multiple children)
.flex-parent {
display: flex;
flex-direction: column;
}
.flex-child-1 {
order: 2;
}
.flex-child-2 {
order: 1;
}
.flex-child-3 {
order: 3;
}
.flex-child-1:hover+.flex-child-2 {
color: #FF3333;
}
<div class="flex-parent">
<h1 class="flex-child-3">I am not changing color</h1>
<a class="flex-child-1">Hover me</a>
<h1 class="flex-child-2">I am changing color</h1>
</div>
Bonus:
CodePen Bonus
http://plnkr.co/edit/j5kGIav1E1VMf87t9zjK?p=preview
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<style>
ul:hover > li
{
opacity: 0.5;
}
ul:hover li:hover
{
opacity: 1;
}
</style>
</head>
<body>
<h1>Hello Plunker!</h1>
<ul>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
<li>Hello</li>
</ul>
</body>
</html>
here is an example how it can be done in pure css , hope it helps somebody
Try this one-line pure CSS solution:
.parent:hover .child:not(:hover) {
/* this style affects all the children *except* the one you're hovering over */
color: red;
}
More info here: https://codyhouse.co/nuggets/styling-siblings-on-hover
Change the H1 tag into a link, style it the same as the normal text maybe?
And then use this,
a:link {color:#FF0000;}
a:hover {color:#FF00FF;}
And it should work when you hover :) you can also make it specific by containing it in a div and then targeting it like this:
.exampledivname a:link {color:#FF0000;}
.exampledivname a:hover {color:#FF00FF;}
This should help.
Someone helped me with this so I thought I would share here as well.
In your first example that is indeed impossible with pure CSS. However, when you wrap it with a parent container you then have the ability to do a bunch of stuff with hovering children.
#banner:hover>h1{
color:red;
}
h1:hover{
color:black !important;
}
#banner{
display:inline-block;
}
.button{
display:inline-block;
font-size:24px;
width:100%;
border:1px solid black;
text-align:center;
}
h1{
padding:0;
margin:0;
}
<div id="banner">
<h1>Heading</h1>
<a class="button" href="#">Button!</a>
</div>
The parent just controls the children who aren't currently being hovered. You then can set hover states for individual elements and classes to make sibling selection possible without JS.
Here is a more advanced example of this in action
https://codepen.io/levyA/pen/gOrdaLJ
For set styles in sibling elements you can use ~ character
in first case when h1 hovered set color for a tag
and in second case when a is hovered, change background color of h1 section
h1:hover ~ a {
color: #e34423;
}
a:hover ~ h1 {
background-color: #eee;
}
This might work, I've recently used this idea to stop sibling elements in an animation.
h1 { color: inherit; }
#banner:hover { color: your choice; }