How to apply child:hover but not parent:hover - css

With the following html, when I hover over child, I get a green background on parent. How can I stop that from happening? I do want the green background if I am hovering outside of the child element.
CSS3 is fine.
.parent {
padding: 100px;
width: 400px;
height: 400px;
}
.parent:hover {
background-color: green;
}
.child {
padding: 100px;
width: 200px;
height: 200px;
}
.child:hover {
background-color: blue;
}
<div class="parent">
<div class="child">Child</div>
</div>

So this is REALLY ugly, but it works (kind of). I'm basically creating a duplicate of parent as a sibling of child. parent-overwrite is hidden by default, then displayed on the hover of child. Chrome doesn't like it unless you use the + selector instead of the ~ selector. This isn't very scalable, but it may work.
As the other guys posted, javascript would likely be a better solution.
<style>
.parent { padding: 100px; width: 400px; height:400px; position: relative; z-index: 998; }
.parent:hover { background-color: green; }
.child { padding: 100px; width: 200px; height:200px; position: relative; z-index: 1000; }
.child:hover { background-color: blue; }
.parent-overwrite { padding: inherit; width: inherit; height: inherit; position: absolute; top: 0; left: 0; z-index: 999; background-color: #FFF; display: none; }
.child:hover ~ .parent-overwrite { display: block; }
</style>
<div class="parent">
<div class="child">Child</div>
<div class="parent-overwrite"></div>
</div>

In 2022:
This can be now achieved using a combination of the :has and :not pseudo-classes, with the following expression:
.parent:hover:not(:has(.child:hover)) {}
To break it down:
.parent
/* When this element is hovered */
:hover
/* but it does not */
:not(
/* have a child node .child, that is also hovered */
:has(.child:hover)
) {
/* apply these rules */
}
A working modification of the original snippet is below:
.parent {
padding: 100px;
width: 400px;
height: 400px;
}
.parent:hover:not(:has(.child:hover)) {
background-color: green;
}
.child {
padding: 100px;
width: 200px;
height: 200px;
}
.child:hover {
background-color: blue;
}
<div class="parent">
<div class="child">Child</div>
</div>
It can also be made recursive by reusing the .parent selector in place of the .child selector.
See browser support here. At the time of writing, all major browser support it—except Firefox, which still has a flawed experimental implementation.

I can only do this with adding additional markup. An empty div needs to be added that essentially functions as the parent background. Take a look at the CSS here.
HTML Part:
<div class="parent">
Parent
<div class="child">
Child
<div class="grandson">
Grandson
<div class="grandson-bg"></div>
</div>
<div class="child-bg"></div>
</div>
<div class="parent-bg"></div>
</div>
CSS part:
article, aside, figure, footer, header, hgroup, menu, nav, section { display: block; }
.parent { display: block; position: relative; z-index: 0;
height: auto; width: auto; padding: 25px;
}
.parent-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.parent-bg:hover { border: 1px solid red; }
.child { display: block; position: relative; z-index: 1;
height: auto; width: auto; padding: 25px;
}
.child-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.child-bg:hover { border: 1px solid red; }
.grandson { display: block; position: relative; z-index: 2;
height: auto; width: auto; padding: 25px;
}
.grandson-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.grandson-bg:hover { border: 1px solid red; }
http://jsbin.com/ubiyo3/edit

The easiest thing to do may be to use JS for this sort of CSS. Maybe you can try to rethink your implementation. Why are you trying to do something like this?

This is not possible using plain-vanilla CSS. You're asking for a pseudo-class of a child (child:hover) to affect the background declaration of a parent. There's no way to specify that sort of thing using regular css.
This can definitely be done using javascript.

I have what i think is a better solution, since it is scalable to more levels, as many as wanted, not only two or three.
I use borders, but it can also be done with whatever style wanted, like background-color.
With the border, the idea is to:
Have a different border color only one div, the div over where the mouse is, not on any parent, not on any child, so it can be seen only such div border in a different color while the rest stays on white.
You can test it at: http://jsbin.com/ubiyo3/13
And here is the code:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Hierarchie Borders MarkUp</title>
<style>
.parent { display: block; position: relative; z-index: 0;
height: auto; width: auto; padding: 25px;
}
.parent-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.parent-bg:hover { border: 1px solid red; }
.child { display: block; position: relative; z-index: 1;
height: auto; width: auto; padding: 25px;
}
.child-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.child-bg:hover { border: 1px solid red; }
.grandson { display: block; position: relative; z-index: 2;
height: auto; width: auto; padding: 25px;
}
.grandson-bg { display: block; height: 100%; width: 100%;
position: absolute; top: 0px; left: 0px;
border: 1px solid white; z-index: 0;
}
.grandson-bg:hover { border: 1px solid red; }
</style>
</head>
<body>
<div class="parent">
Parent
<div class="child">
Child
<div class="grandson">
Grandson
<div class="grandson-bg"></div>
</div>
<div class="child-bg"></div>
</div>
<div class="parent-bg"></div>
</div>
</body>
</html>

Related

how with the filter css property pop-up in this element to leave the background white?

how with the filter css property pop-up in this element to leave the background white?
need to leave the inner white when fillter , and I don't know how
now
need
.first{
width: 200px;
height: 50px;
border: solid;
background: white;
}
.first span{
display: none;
background: white;
}
.first:hover{
filter: brightness(55%);
}
.first span:hover{
width: 100px;
height: 25px;
border: solid;
display: block;
}
<div class="first"> <span>alert</span></div>
<div class="first"><span>alert</span></div>
you can use this style
.first{
width: 200px;
height: 50px;
border: solid;
background: white;
}
.first span{
display: none;
background: white;
}
.first:hover{
background: #0000004f;
}
.first:hover span{
width: 100px;
height: 25px;
border: solid;
display: block;
}
Whenever you use filter, all children of that element will inherit it.
To achieve what you want you need to make it a sibling. Here is an example:
HTML:
<div class="block">
<div class="block-filter"></div>
<span class="block-message">alert</span>
</div>
CSS:
.block {
position: relative;
width: 200px;
}
.block-filter {
height: 50px;
width: 100%;
border: solid;
background: white;
}
.block-message {
display: none;
background: white;
}
.block-filter:hover {
filter: brightness(55%);
}
.block-filter:hover + span {
filter: unset;
position: absolute;
top: 0;
left: 0;
border: solid;
display: block;
pointer-events: none;
background: white;
}
https://codepen.io/diego-fortes/pen/vYBJoeP

Border-radius and overflow hidden with child background

I've got a problem with border-radius on wrapper that contains an overflow hidden.
I use a before pseudo element (pink background) to fill the wrapper's background. The wrapper has already a background (blue).
#wrapper {
background: blue;
border: 2px solid pink;
border-radius: 12px;
height: 90px;
overflow: hidden;
position: relative;
width: 300px;
}
#wrapper::before {
background: pink;
content: '';
display: block;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 50%;
}
<div id="wrapper"></div>
With this example, we can see an unwanted blue pixel on the top and bottom left corner.
The pseudo element must be in position absolute to apply animation. I removed the animation for the example.
How can I fix this?
A fix is here. Apply overflow:hidden an width:300px to the outer div #container.
#container {
width: 300px;
overflow: hidden;
border-radius: 12px;
}
#wrapper {
height: 90px;
background: blue;
border-radius: 12px;
position: relative;
box-sizing: border-box;
border: 2px solid pink;
}
#wrapper::before {
background: pink;
content: '';
display: block;
height: 100%;
right: -30px;
position: absolute;
top: 0;
width: 30px;
border-radius: 50%;
transition: transform 0.3s;
}
#wrapper:hover::before {
transform: scale3D(10, 10, 1);
}
<div id="container">
<div id="wrapper"></div>
</div>
You found a really interesting rendering issue. My idea to solve it, is switch the colors and logic a little:
#wrapper {
background: pink;
border: 2px solid pink;
border-radius: 12px;
height: 90px;
overflow: hidden;
position: relative;
width: 300px;
}
#wrapper::before {
background: blue;
content: '';
display: block;
height: 100%;
right: 0;
position: absolute;
top: 0;
width: 50%;
}
<div id="wrapper"></div>

Firefox not ignoring fixed position elements when outside container width

I wasn't sure of the best way to explain this, but if you look at the example snippet in Chrome or Safari, the orange div does not cause the document to scroll horizontally when the window is narrower than the blue container. This is the desired behavior.
However, in Firefox, if you make the window narrow it counts the orange box as content that needs to be able to be scrolled to, causing the document to scroll to the right in an odd way that shifts the body content to the left and is ugly. What's also strange is that you'll notice the green box on the left DOESN'T cause it to have scrollable space to the left...is this a bug, or why is this happening?
Anyone else encountered this?
* {
box-sizing: border-box;
}
.wrapper {
max-width: 700px;
height: 200px;
margin: 0 auto;
}
.banner {
width: 100%;
height: 100%;
padding: 10px;
background-color: blue;
position: relative;
transform: scale(1);
color: #ffffff;
}
.banner:before, .banner:after {
content: '';
width: 100px;
height: 100%;
position: fixed;
left: -100px;
top: 0;
background-color: green;
}
.banner:after {
left: 100%;
background-color: orange;
}
.content {
width: 100%;
height: 300px;
padding: 10px;
background-color: #f1f1f1;
margin-top: 40px;
}
<div class="wrapper">
<div class="banner">Banner</div>
<div class="content">Content</div>
</div>
You can wrap that in an element that will scale with the viewport and set overflow: hidden on that element. You can also remove the transform: scale() from .banner and use position: absolute on the pseudo elements, unless scale(1) is needed for some reason.
* {
box-sizing: border-box;
}
header {
overflow: hidden;
}
.wrapper {
max-width: 700px;
height: 200px;
margin: 0 auto;
}
.banner {
height: 100%;
padding: 10px;
background-color: blue;
position: relative;
color: #ffffff;
}
.banner:before, .banner:after {
content: '';
width: 100px;
height: 100%;
position: absolute;
left: -100px;
top: 0;
background-color: green;
}
.banner:after {
left: 100%;
background-color: orange;
}
.content {
height: 300px;
padding: 10px;
background-color: #f1f1f1;
margin-top: 40px;
}
<header>
<div class="wrapper">
<div class="banner">Banner</div>
<div class="content">Content</div>
</div>
</header>

Control the :after of a div when hover on another element

I want to control after of box2 when hovering on box1.
I test this code but it didn't work.so...whats the problem?
.box1:hover .box2:after{SOME CSS}
.box1 , .box2 , .box2:after{
width: 100px;
height: 100px;
background-color: #ccc;
margin: 10px;
display: inline-block;
}
.box2:after {
content: 'Box2:after';
position: relative;
display: inline-block;
left: 200px;
top: -30px;
}
.box1:hover ~ .box2:after {
background-color: red
}
<div class="box1">BOX 1:hover my</div>
<div class="box2">Box 2</div>

How to make an element positioned into right:0, if it already has left:0 style in one of it's class

I have an element with class A, with rules:
.A {
left: 0px;
}
For some reason, I need to make the element at the right position inside the container and I cannot exclude A class.
Specificity is your friend here:
Here's a couple of options....
Override the class using additional specificity such as another class (or ID)
.container {
height: 50vh;
position: relative;
width: 50%;
bordeR: 1px solid grey;
margin: auto;
}
.A {
position: absolute;
height: 25px;
width: 25px;
left: 0;
background: #000;
margin-bottom: 1em;
}
.A.right {
left: auto;
right: 0;
background: red;
}
<div class="container">
<div class="A"></div>
<div class="A right"></div>
</div>
or a nth-child selector
.container {
height: 50vh;
position: relative;
width: 50%;
bordeR: 1px solid grey;
margin: auto;
}
.A {
position: absolute;
height: 25px;
width: 25px;
left: 0;
background: #000;
margin-bottom: 1em;
}
.A:nth-child(2) {
left: auto;
right: 0;
background: red;
}
<div class="container">
<div class="A"></div>
<div class="A"></div>
</div>

Resources