no jquery please
I have the following menu with class=menu-list, I want that on hover of nested/child ul li item, to change background color to white of parent li element
Code and working demo:
nav .menu-list{
background: white;
position: absolute;
margin-top: 60px;
padding: 12px 0;
display: none;
width: 68vw;
height: 100vh;
}
nav .menu-list li{
background: white;
display: block;
color: #000000;
position: relative;
padding: 0;
border-left: 24px white solid;
}
nav .menu-list li:hover{
background: #eee;
border-left: 24px #eee solid;
}
nav ul li:focus {
background: white;
}
nav ul li:focus ul {
display: block;
position: relative;
left: 0;
margin-left: -24px;
}
nav ul li ul li:hover {
background: white;
}
<nav>
<ul class="menu-list" style="display: block;">
<li tabindex="1" onclick="location.href='#/work'; dimScreen()">Work</li>
<li tabindex="2" onclick="dimScreen()">About
<ul>
<li onclick="location.href='#/about/what-we-do'">What we do</li>
<li onclick="location.href='#/about/how-we-work'">How we work</li>
<li onclick="location.href='#/about/leadership'">Leadership</li>
</ul>
</li>
</ul>
</nav>
no jquery please
I have the following menu with class=menu-list, I want that on hover of nested/child ul li item, to change background color to white of parent li element
Code and working demo:
nav .menu-list{
background: white;
position: absolute;
margin-top: 60px;
padding: 12px 0;
display: none;
width: 68vw;
height: 100vh;
}
nav .menu-list li{
background: white;
display: block;
color: #000000;
position: relative;
padding: 0;
border-left: 24px white solid;
}
nav .menu-list li:hover{
background: #eee;
border-left: 24px #eee solid;
}
nav ul li:focus {
background: white;
}
nav ul li:focus ul {
display: block;
position: relative;
left: 0;
margin-left: -24px;
}
nav ul li ul li:hover {
background: white;
}
<nav>
<ul class="menu-list" style="display: block;">
<li tabindex="1" onclick="location.href='#/work'; dimScreen()">Work</li>
<li tabindex="2" onclick="dimScreen()">About
<ul>
<li onclick="location.href='#/about/what-we-do'">What we do</li>
<li onclick="location.href='#/about/how-we-work'">How we work</li>
<li onclick="location.href='#/about/leadership'">Leadership</li>
</ul>
</li>
</ul>
</nav>
Lame paint screenshot to explain better:
Share Improve this question asked Oct 11, 2015 at 22:20 JekaJeka 1,7003 gold badges23 silver badges38 bronze badges 2-
1
As a short rundown of what you can do, you want to bind a mouseover event on your child element. In that event, you want to find the parent, in some form of
var parent = evt.parentNode
, and then you can manipulate the style byparent.style.background='some hex color'
– David Li Commented Oct 11, 2015 at 22:33 - I wrote out a javascript solution for your reference – David Li Commented Oct 11, 2015 at 22:43
4 Answers
Reset to default 2First thing, you can't do this with CSS. CSS has no concept of what it's parent element is.
As for javascript, you can use mouse events. Here's an example:
var parentOn = function(e) {
e.target.parentNode.style.backgroundColor = '#9d7';
}
var parentOff = function(e) {
e.target.parentNode.style.backgroundColor = '#97a';
}
var children = document.querySelectorAll('.child');
for (var x = 0; x < children.length; x ++) {
children[x].addEventListener('mouseover', parentOn);
children[x].addEventListener('mouseout', parentOff);
};
A few things to note:
Any JavaScript DOM query will return an array of nodes, so you must iterate over them to avoid error. JQuery hides this nicely so it can be confusing.
the mouseenter and mouseleave bination is subtley different from mouseover and mouseout, you can find out more here
Working out how to use JavaScript to add and remove classes would be better than using inline styles. This answer will help. You'll be able to re-use the styles and it'll be easier to maintain - I'd such creating a utility function to handle this, like JQuery's
addClass()
.Using named function variables is a bit clearer than anonymous functions, and more re-usable.
https://jsfiddle/chwbuvum/6/
Here's a pure CSS solution
As Tony Leigh pointed out, you cannot do exactly what you asked using pure CSS, but you can make it look like you want.
The changed lines in the CSS are mented in the snippet, and the main change in the HTML is the addition of the span tag in the top-level list elements.
The main idea is that each top-level li
remains white, while the enclosed span
turns gray on hover. That way, hovering over a sub-list doesn't change color of the parent li
.
Code Snippet
nav .menu-list{
background: white;
position: absolute;
margin-top: 60px;
padding: 12px 0;
display: none;
width: 68vw;
height: 100vh;
}
nav .menu-list li{
background: white;
display: block;
color: #000000;
position: relative;
padding: 0;
/* changed from border to background color
border-left: 24px white solid;
*/
padding-left:24px; /* added to put back the "border-left" area */
}
nav .menu-list li:hover{
background: white; /*changed from #eee to white */
/* changed from border to background color
border-left: 24px #eee solid;
*/
}
/* start added blocks */
nav .menu-list li span {
width: 100%;
display:block;
position:relative;
left:-24px;
padding-left:24px;
}
nav .menu-list li span:hover{
background: #eee;
}
/* end added blocks */
nav ul li:focus {
background: white;
}
nav ul li:focus ul {
display: block;
position: relative;
left: 0;
margin-left: -24px;
}
nav .menu-list li ul li:hover {
background: #eee;
}
<nav>
<ul class="menu-list" style="display: block;">
<li tabindex="1" onclick="location.href='#/work'; dimScreen()"><span>Work</span></li>
<li tabindex="2" onclick="dimScreen()"><span>About</span>
<ul>
<li onclick="location.href='#/about/what-we-do'">What we do</li>
<li onclick="location.href='#/about/how-we-work'">How we work</li>
<li onclick="location.href='#/about/leadership'">Leadership</li>
</ul>
</li>
</ul>
</nav>
Thanks everyone for trying but I only needed to add this to make it work
.menu-list li:hover {
background: #eee;
}
.menu-list li:focus {
background: white;
}
Here's a code based solution:
JS
var listElements = document.getElementsByClassName('submenu');
for (var i = 0; i < listElements.length; i++) {
listElements[i].addEventListener("mouseenter", function(evt) {
evt.target.parentNode.style.background = "red";
});
listElements[i].addEventListener("mouseleave", function(evt) {
evt.target.parentNode.style.background = "black";
});
}
HTML CHANGE
<ul class="menu-list" style="display: block;">
<li tabindex="1" onclick="location.href='#/work'; dimScreen()">Work</li>
<li tabindex="2" onclick="dimScreen()">About
<ul class='submenu'>
<li onclick="location.href='#/about/what-we-do'">What we do</li>
<li onclick="location.href='#/about/how-we-work'">How we work</li>
<li onclick="location.href='#/about/leadership'">Leadership</li>
</ul>
</li>
</ul>
As you can see, for each of your submenus you will have, I added an additional submenu
class to differentiate between the main menu and submenu. When you leave each element, it will change the background of the parent to black. When you enter, it will change it to red, based on the mouseenter
and mouseleave
events.
What it does is find the parent node and then manipulate the styling of that element.