CSS - Manipulate another element on hover - html

I need to change #hidden to display:block when #aaa is hovered over. It's not working because #aaa isn't on the same level as #hidden - is there a way to manipulate a completely separate element on hover? I'm trying to make a CSS-based nav w/ a subnav and show the respective subnav when a nav item is hovered over.
HTML:
<div class="cheetahContainer">
<div id="cheetah">
<p>Cheetah</p>
</div>
</div>
<div id="hidden">
<p>A cheetah is a land mammal that can run up 2 60mph!!!</p>
</div>
CSS:
#cheetah {
background-color: red;
text-align: center;
}
a {
color: blue;
}
#hidden {
display:none;
color: orange;
}
#cheetah:hover{
background-color:green;
}
#cheetah:hover + #hidden {
display:block;
}
http://jsfiddle.net/LgKkU/575/

Since your link is not a sibling of your #hidden div (thus you can't use the immediate adjacency selector), you should change last rule with
.cheetahContainer:hover + #hidden {
display:block;
}

Hovering over an element can only affect child elements in css. Here's a fix for your example:
<div class="cheetahContainer">
<div id="cheetah">
<p>Cheetah</p>
</div>
<div id="hidden">
<p>A cheetah is a land mammal that can run up 2 60mph!!!</p>
</div>
</div>
However, I would recommend changing the css to something like this:
.cheetahContainer:hover .hidden {
display: block;
}
Changed out id's for classes and added hover to parent element so that hovering over the revealed text doesn't revert back to display:none;

It is not a direct sibling so you need to use js
Here is an example of what to do:
var $cheetah = document.getElementById('cheetah');
var $hidden = document.getElementById('hidden');
$cheetah.addEventListener('mouseover', function() {
$hidden.style.display = 'block';
});
$cheetah.addEventListener('mouseout', function() {
$hidden.style.display = 'none';
});
Or you can use the container:
.cheetarContainer:hover + #hidden {
display: block;
}

Related

How can I get two anchor elements to hover together? [duplicate]

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; }

How to set a default styling to element if :target doesn't exist

I have a header with 3 links, all linking to a specific div with a corresponding id:
body {
font-size: 32px;
}
.links {
display: flex;
a {
padding: 10px;
}
}
.box:not(:target) {
display: none;
}
#box1 {
background-color: crimson;
}
#box2 {
background-color: darkgreen;
}
#box3 {
background-color: gold;
}
<div class="links">
Box1
Box2
Box3
</div>
<div class="box" id="box1">Box1 content</div>
<div class="box" id="box2">Box2 content</div>
<div class="box" id="box3">Box3 content</div>
I want to use the CSS pseudo class to turn the selected element from display:none to display:block when targetted. I achieved this using .box:not(:target) { display:none }.
The problem is that I would like to default the boxes to show the first box (#box1) if :target does not exist amongst the three boxes with css only if possible, any help would be greatly appreciated!
Follow below the snippet, hope your problem will fix with html and css,
body {
font-size: 32px;
}
.links {
display: flex;
a {
padding: 10px;
}
}
.box:not(:target) {
display: none;
}
#box1{
display: block;
}
#box2:target ~ #box1,
#box3:target ~ #box1{
display: none;
}
#box1 {
background-color: crimson;
}
#box2 {
background-color: darkgreen;
}
#box3 {
background-color: gold;
}
<div class="links">
Box1
Box2
Box3
</div>
<div class="box" id="box2">Box2 content</div>
<div class="box" id="box3">Box3 content</div>
<div class="box" id="box1">Box1 content</div>
the box1 is default and when you trigger the box2, box3 you can see box1 will get display none.
mainly it's working for "general sibling selector (~)"
Create new css class called BoxControl consider this in all <a> elements for trigger show/hide event.
Then Add .active css class and add it to default class list of the element you want to show in first view as shown bellow.
Finally, implement JS as for your HTML structure tell that is your best option otherwise you'll have to modify your HTML.
SCSS/JS
Codepen Link
CSS/JS
// Capture all elements of <a> output should be in an array
var box = document.getElementsByClassName("boxControl");
// Create new variable i stands for index to be used in for loop
var i;
// Loop through all elements been found in box variable
for (i = 0; i < box.length; i++) {
// Add Event Listener of Click for <a> elements found in the variable box
box[i].addEventListener("click", function(e) {
// Add e in callback function trace the element triggered this event
// In other words, which button has been clicked
var clicked =
e.target.getAttribute("href");
// Tricky bit: As per your request they should be at least
// one default active element otherwise or else will not remove any active class
if (document.querySelector(".active")) {
document.querySelector(".active").classList.remove("active");
// Use value of captured attribute (href) to target and toggle the new active class
document.querySelector(clicked).classList.toggle("active");
// Not found any active css class (box)
} else {
var clicked = e.target.getAttribute("href");
document.querySelector(clicked).classList.toggle("active");
}
})
};
body {
font-size:32px;
}
.links {
display:flex;
}
.links a {
padding:10px;
}
.active {
display:block!important;
}
#box1 {
background-color:crimson;
display: none;
}
#box2 {
background-color:darkgreen;
display: none;
}
#box3 {
background-color:gold;
display:none;
}
<div class="links">
Box1
Box2
Box3
</div>
<div class="box active" id="box1">Box1 content</div>
<div class="box" id="box2">Box2 content</div>
<div class="box" id="box3">Box3 content</div>

How to hide a div from another div using CSS

I want to hide a div con1 when i hover div con2 and vice versa. I am able to hide con2 when i hover con1 but can't do the same vice-versa. Why it is not working when i hover con2 to hide con1.
Below are the codes:
<html>
<head>
<title>Home</title>
<style type="text/css">
#con1{
float: left;
width: 500px;
height: 300px;
background: #f00;
}
#con2{
float:left;
width: 500px;
height: 300px;
background: #808;
}
#con1:hover ~#con2{
visibility:hidden;
}
#con2:hover ~#con1{
display:none;
}
</style>
</head>
<body>
<div id="con1">
</div>
<div id="con2">
</div>
</body>
</html>
Example: http://jsfiddle.net/mendesjuan/s8bbe/
I believe this is not possible with the general sibling selector as it only applies to elements after it in the html-structure. See more: http://css-tricks.com/child-and-sibling-selectors/
A possible (althought not especially elegant solution):
http://jsfiddle.net/s8bbe/4/
<div id="wrapper">
<div id="con1">
</div>
<div id="con2">
</div>
#con1{
float: left;
width: 500px;
height: 300px;
background: #f00;
}
#con2{
float:left;
width: 500px;
height: 300px;
background: #808;
}
#con1:hover ~#con2{
visibility:hidden;
}
#wrapper:hover #con1:not(:hover){
visibility:hidden;
}
Example: http://jsfiddle.net/s8bbe/5/
#KnutSv's solution is great. Here's an add-on if using more than 2 divs.
<div id="con-wrapper">
<div id="con1">
</div>
<div id="con2">
</div>
<div id="con3">
</div>
</div>
And a one-line css with :hover, :not(:hover).
#con1{
float: left;
width: 500px;
height: 300px;
background: #f00;
}
#con2{
float:left;
width: 500px;
height: 300px;
background: #808;
}
#con3{
float:left;
width: 500px;
height: 300px;
background: #606;
}
#con-wrapper:hover > div:not(:hover) {
visibility: hidden;
}
Using "> div" will target all #con-wrapper direct div children, which are not hovered, and hide them.
Use #con-wrapper:hover > div[id^=con]:not(:hover) if only cons needed to be targeted.
Putting the divs in one container div you can hide all contained divs on hoover, but not the actually 'hovered over' one with:
div:hover div {
visibility: hidden;
}
div:hover div:hover {
visibility: visible;
}
See demo: http://jsfiddle.net/TcPJZ/3/
EDIT: It actually works well for arbitrary number of divs (see demo).
Maybe you are using wrong selectors
try this
.con2:hover ~ div {display:none}
But this is "Hard code" if you will want to add more divs before con-2 they will be dissappearing too
I try it on jsfiddle and I get the problem.
When you have this:
<div id="con1">
</div>
<div id="con2">
</div>
Hover on "con1" works, but when you change the positions:
<div id="con2">
</div>
<div id="con1">
</div>
Now it's "con2" which is working and now not "con1".
So , I don't know how to fix it, but I can tell you about make it by Javascript/Jquery.
I think that can be solve the problem.
CSS doesn't support previous sibling selection. If you still want to have a previous sibling selector then you should look in to javascript.
var con1 = document.getElementById('con1');
var con2 = document.getElementById('con2');
function displayElem(el, property, value){
el.style[property] = value;
}
con1.onmouseover = displayElem.bind(null, con2, 'display', "none");
con1.onmouseout = displayElem.bind(null, con2, 'display', "");
con2.onmouseover = displayElem.bind(null, con1, 'visibility', "hidden");
con2.onmouseout = displayElem.bind(null, con1, 'visibility', "");
Working Fiddle
In the above fiddle, I even moved the next sibling selection to javascript so that to let you keep the code structured. if you don't want to do so, then happily don't events to the first element :)
it will be easily done by using below code using jquery , why you depend only on css
$("#con1").hover(function(){
$("#con2").css("visibility","hidden");
},function(){
$("#con2").css("visibility","visible");
});
here is the working sample http://jsfiddle.net/5jRXm/

Why is General sibling combinator not always working?

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.

Change color of sibling elements on hover using CSS

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; }