Reputation: 61
I have the following code. How can I affect the status of other links when the cursor is on a link? For example I would like that when the mouse is over a link I can affect the opacity of the other links. I thought of a way to add the event to the link parent nav links and then check if the event is really on the link or outside.
Is the method I started good or I should approach event delegation
const nav = document.querySelector(".nav__links");
const item = Array.from( document.querySelectorAll(".nav__item"));
const link = Array.from( document.querySelectorAll(".nav__link"));
link.forEach(t => t.addEventListener('mouseover' ,function(e){
const targetLink = e.target ;
console.log(targetLink) ;
if ( t !==targetLink) {
t.style.opacity = 0.2;
}
})) ;
.nav__links {
display: flex;
align-items: center;
list-style: none;
justify-content:center;
}
.nav__item {
margin-left: 0.7rem;
}
<ul class="nav__links">
<li class="nav__item">
<a class="nav__link" href="#">Home</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">About</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">Testimonials</a>
</li>
Upvotes: 1
Views: 125
Reputation: 1074028
If you're okay with dimming the options when the mouse is over the nav list and then not dimming the active one, you can do this just with CSS (I added a bit of transition to it, but you can remove that):
.nav__links:hover li {
opacity: 0.2;
transition: opacity 0.1s;
}
.nav__links:hover li:hover {
opacity: 1;
}
Live Example:
.nav__links {
display: flex;
align-items: center;
list-style: none;
justify-content: center;
}
.nav__links:hover li {
opacity: 0.2;
transition: opacity 0.1s;
}
.nav__links:hover li:hover {
opacity: 1;
}
.nav__item {
margin-left: 0.7rem;
}
<ul class="nav__links">
<li class="nav__item">
<a class="nav__link" href="#">Home</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">About</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">Testimonials</a>
</li>
</ul>
That also has the advantage that there's no flashing as you move the mouse across from one nav item to the next (going out of one li
, over the ul
, then into the next li
).
But if you only want them dimmed when one of the nav items is hovered, I don't think we can do it just with CSS because there's no general sibling combinator (there's just the next sibling [+
] or subsequent sibling [~
]).
But we can let CSS do most of the work. The trick is making sure that we un-dim things when the mouse is no longer over any of the nav items. Remember that the mouse can jump out of elements (for instance, if the user Alt+Tabs to a different app, moves the mouse, and then tabs back to the page), so we have to be fairly aggressive about un-dimming things.
Here's a version that uses a passive mousemove
handler on the document
. Normally I'd avoid a mousemove
handler on document
since it will get fired a lot, but what we're doing inside the handler is really quick:
document.addEventListener("mouseover", event => {
const li = event.target.closest(".nav__links li");
if (li) {
nav.classList.add("dimmed");
} else {
nav.classList.remove("dimmed");
}
}, {passive: true});
Then we throw some CSS at it:
.nav__links.dimmed li {
opacity: 0.2;
transition: opacity 0.1s;
}
.nav__links.dimmed li:hover {
opacity: 1;
}
Live Example:
const nav = document.querySelector(".nav__links");
document.addEventListener("mouseover", event => {
const li = event.target.closest(".nav__links li");
if (li) {
nav.classList.add("dimmed");
} else {
nav.classList.remove("dimmed");
}
}, {passive: true});
.nav__links {
display: flex;
align-items: center;
list-style: none;
justify-content: center;
}
.nav__links.dimmed li {
opacity: 0.2;
transition: opacity 0.1s;
}
.nav__links.dimmed li:hover {
opacity: 1;
}
.nav__item {
margin-left: 0.7rem;
}
<ul class="nav__links">
<li class="nav__item">
<a class="nav__link" href="#">Home</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">About</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#">Testimonials</a>
</li>
</ul>
Upvotes: 3