Update the :hover effect on elements within a pseudo element

Within our menu, I have a main menu item and its sub-items change color to orange on hover. Additionally, I've implemented some JavaScript to create a toggle for collapsing/expanding the menu. However, due to the positioning of the span element over the parent list item, hovering on the toggle triggers the color change effect. I'm currently exploring methods (either utilizing Compass or jQuery) to override the hover style on the list if the toggle is being hovered upon.

Since we're using Drupal, the HTML structure is quite complex, but here's a simplified version:

<li class="menu__item is-expanded last-expanded">
  <span class="menu__link nolink">About</span>
  <span class="menu__link nolink expand"> </span> <!-- added dynamically by jQuery for collapse/expand functionality -->
  <ul class="menu">
    <li><a href="mission.html">Mission</a></li>
    <li><a href="team.html">Team</a></li>
  </ul>
</li>

Below is the jQuery code snippet used:

jQuery(document).ready(function(){
      $(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'>&nbsp;</span>");
      $(".front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand collapse'>&nbsp;</span>");
      $("#block-menu-block-1 ul li li").css({ display: "block" });
      $(".not-front #block-menu-block-1 ul li li").css({ display: "none" });
      $('#block-menu-block-1 .menu__link.nolink').click(function(){
        $('#block-menu-block-1 ul li li').toggle('fast');
        $( ".menu__item.is-expanded.last.expanded span.menu__link.nolink.expand" ).toggleClass( "collapse" );
      });
 });

And here are the Sass styles applied:

.menu__item:hover a,
.menu__item:hover span {
  color: $orange;
}

Edit: Apologies! Earlier I wanted to share a Sassmeister link, but their site was down. There was also a reference to the dev site, which has been removed now.

Edit: Initially, I believed the following code would resolve the issue, but it didn't work as expected:

jQuery(".menu__item span.expand").mouseover(function(e) {
        jQuery("menu__item:hover a, .menu__item:hover span").toggleClass( "stay-gray" );
});

In conjunction with the above jQuery, here is the corresponding Sass styling:

.menu__item:hover a,
.menu__item:hover span {
  color: $orange;
  border-color: $orange;
  &.stay-gray {
    color: $darkGray;
    border-color: $darkGray;
  }
}

Answer №1

To prevent the event from spreading to span.expand elements, you can do the following:

$("span.expand").mouseover(function(e) {
    e.stopImmediatePropagation();
});

RECENT UPDATE: The initial use of `stopPropagating` did not achieve the desired result. After considering the user's suggestion, an alternative solution was implemented:

Add two new CSS rules:

.stay-gray a.menu__link {
  border-bottom-color: #474E51 !important;
}
.stay-gray, .stay-gray a.menu__link {
  color: #474E51 !important;
}

Include the following code at the end of your

jQuery(document).ready(function(){ ...
:

toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);

By adopting this method:

jQuery(document).ready(function(){
  jQuery(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'>&nbsp;</span>");
  jQuery(".front .menu__item.is-expanded.last.ex... (truncated)</answer1>
<exanswer1><div class="answer accepted" i="21920241" l="3.0" c="1392918162" m="1393014476" v="1" a="R3VpbGxlcm1vIEd1dGkmIzIzMztzdGF5">
<p>Why not consider halting the event propagation on the <code>span.expand components:

$("span.expand").mouseover(function(e) {
    e.stopPropagation();
});

UPDATE: Despite trying out 'stopPropagating', it did not produce the intended effect. Thus, in line with the suggestion made by the original poster, we formulated an alternate solution:

Incorporate two additional CSS guidelines:

.stay-gray a.menu__link {
  border-bottom-color: #474E51 !important;
}
.stay-gray, .stay-gray a.menu__link {
  color: #474E51 !important;
}

Subsequently, append these instructions towards the conclusion of the

jQuery(document).ready(function(){ ...
:

toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);

Upon employing this method:

jQuery(document).ready(function(){
  jQuery(".not-front .menu__item.is-expanded.last.... (truncated)</answer1></answer1>
<exanswer1><div class="answer accepted" i="21920239" l="3.0" c="1392918162" m="1393014476" v="1" a="R3VpbGxlcm1vIEd1dGkmIzIzMztycmV6" ai="806975">
<p>Perhaps you should consider not allowing the event to propagate on the <code>span.expand elements:

$("span.expand").mouseover(function(e) {
    e.stopPropagation();
});

UPDATE: The use of `stopPropagating` did not achieve the desired result. Therefore, following the suggestion provided by the OP, we came up with this alternative solution:

Introduce two additional CSS rules:

.stay-gray a.menu__link {
  border-bottom-color: #474E51 !important;
}
.stay-gray, .stay-gray a.menu__link {
  color: #474E51 !important;
}

Then add these lines at the end of the

jQuery(document).ready(function(){ ...
:

toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);

With this approach:

jQuery(document).ready(function(){
  jQuery(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'>&nbsp;</span>");
  jQuery(".front .menu__item.is-expanded.last.ex... (truncated)</answer1>
<exanswer1><div class="answer accepted" i="21920239" l="3.0" c="1392918162" m="1393014476" v="1" a="R3VpbGxlcm1vIEd1dGkmIzIzMztycmV6" ai="806975">
<p>Maybe you could try stop propagating the event on the <code>span.expand elements:

$("span.expand").mouseover(function(e) {
    e.stopPropagation();
});

EDIT: stopPropagating didn't work. So, retaking the idea proposed by the OP, we figured out this solution:

Add two new CSS rules:

.stay-gray a.menu__link {
  border-bottom-color: #474E51 !important;
}
.stay-gray, .stay-gray a.menu__link {
  color: #474E51 !important;
}

And then add this lines at the end of the

jQuery(document).ready(function(){ ...
:

toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);

This way:

jQuery(document).ready(function(){
  jQuery(".not-front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand'>&nbsp;</span>");
  jQuery(".front .menu__item.is-expanded.last.expanded span").after("<span class='menu__link nolink expand collapse'>&nbsp;</span>");
  jQuery("#block-menu-block-1 ul li li").css({ display: "block" });
  jQuery(".not-front #block-menu-block-1 ul li li").css({ display: "none" });
  jQuery('#block-menu-block-1 .menu__item.is-expanded').click(function(){
      jQuery('#block-menu-block-1 ul li li').toggle('fast');
      jQuery( ".menu__item.is-expanded.last.expanded span.menu__link.nolink.expand" ).toggleClass( "collapse" );
  });
  toggleStayGray=function(e){ jQuery(e.target).siblings().toggleClass('stay-gray') };
  jQuery('.menu span.expand').mouseover(toggleStayGray).mouseout(toggleStayGray);
});

When hovering over the span.expand element, the stay-gray class is toggled on its siblings, applying new styles to them and their a.menu__link descendants. The stay-gray class is toggled off when the mouse leaves.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

HTML5 Mouse Canvas

Here's a simple example of what's happening: function handleClick(event) { ... } canvas.addEventListener("click", handleClick, false); function drawRectangle(x, y) { context.fillRect(x, y, 16, 16); }; ...

Minimize and dismantle the object deconstruction/allocation

Imagine I have two basic objects and I want to combine their properties to create a third object. It works smoothly with this code: (()=>{ const firstObj = {a: 2, b: 3} const secondObj = {a: 100, c: 5} return {...firstObj, ...secondObj} })() // { ...

Variable Returned by AJAX

I am attempting to send a variable using a select box via POST method, then use AJAX to submit the data and finally leverage that variable on the original page to update SQL queries. Below is the code snippet I currently have: <script type="text/j ...

Resizing a horizontal menu causes items to disappear gradually

Hello there! I'm in search of a JavaScript plugin that can create a horizontal menu with an effect similar to what you see on this website: horizontal menu Specifically, I need the functionality where items in the menu disappear and are added to a dr ...

Issues with cross-domain AJAX JSONP requests not functioning in Internet Explorer 8

After enabling CORS support using jquery-1.9.1, I made an ajax request with jsonp callback support from the server side. $.ajax({ type: 'GET', url: url, async: false, contentType: "application/json", jsonpCallback: 'jso ...

Tips for transitioning from an old link to a new link within an MVC framework

Is there a way to redirect an old link to a new link in MVC? In Google search results, my old URL was cached as www.abcd.com/product?id=64 however, my new URL is now www.abcd.com/product/sample How can I set up a redirect so that when a user clicks on th ...

Tips for dynamically updating an HTML value with Javascript

Summary of My Issue: This involves PHP, JS, Smarty, and HTML <form name="todaydeal" method="post"> <span id="fix_addonval"></span> <input type="radio" name="offer" id="offer_{$smarty.section.mem.index+1}" value="{$display_offe ...

My HTML elements are not displaying in the correct order. Any suggestions on how to resolve

Hi, I am currently working on a website using HTML, CSS, and JS. I have encountered a small issue in the HTML section. Here is the code snippet: window.onscroll = function() { changeOnScroll() }; function changeOnScroll() { var winScroll = docum ...

Can the ES2016 Proxy be used to intercept the "typeof" operation?

Can a handler property be defined to intercept typeof proxyObject? It is not mentioned in any of the traps listed on Mozilla. ...

Calculating totals by adding up values from a variable number of form fields

One of the challenges I encountered was dynamically adding and removing fields in a form using jQuery, specifically looking at RailsCast #196/7. In my scenario, I'm working on a purchase form where I want to initialize with a default quantity of one. ...

Is there a way to transform vanilla JavaScript code into Vue.js code?

// Vanilla JS Code Conversion const app = new Vue({ el: '#app', methods: { // Logged out Events loginHelp: function() { this.$refs.forgotten.style.display = 'flex'; this.$refs.login.style.display = 'none&apo ...

Creating a Javascript Polling feature in a Ruby on Rails application

I'm completely new to using javascript and I am currently working on implementing polling in a rails application to display a simplified feed of activities from an activity model. I am closely following the Railscast tutorial on polling which can be f ...

Finding the index of a clicked link using jQuery

This is the code I have written: <div> <h2><a href="link-here">Link Text</a></h2> <p>Description</p> <h2><a href="link-here">Link Text</a></h2> <p>Description</p> <h2>< ...

Tips for finding the index of data in Cesium

After successfully completing the tutorial on building a flight tracker, I am facing a challenge. I want to access the current index of my data at any given time while my app is running cesium and displaying the airplane animation following the flight path ...

When working with a destination module, what is the best method for storing the value that is returned from an

I have a simple function that exports data passed into a function expression. In a separate node module, I am utilizing this imported function by passing in parameters. The function is being called within a router.post method as shown below: Below is the ...

What is the best way to ensure the website title is displayed properly on a mobile browser?

Concern I have been encountering difficulties while constructing a portfolio website using bootstrap 5. The issue arises with the navbar, causing the Title to overlap the hamburger menu and extend beyond the edge of the screen. Strangely enough, this prob ...

Incorporating partial page loading with PHP and ID links

Having some trouble with partial page loads and PHP variables. Currently, I have it set up to work, but when trying to include a PHP variable, it seems to be causing issues. The page successfully loads without the variable: <li><a href="javascri ...

Unusual Occurrence in Angular 2: Modifications in one tab affecting another

As a beginner in Angular 2, I am working on building a basic CRUD application with authentication. I have successfully created a simple login form that submits uid/password to a NodeJS backend through an Angular service using ngForm. I then display the aut ...

Nest JS encountering an error due to an undefined property

Recently, my application was running smoothly until I attempted to fetch the documentation using Swagger. It seems like there might be a dependency issue causing it to stop working, but I can't pinpoint the root of the problem. An error message keeps ...

Designing image hover effects using CSS

I am looking for guidance on how to achieve a similar effect to the one shown here: Specifically, I want to create a box with images that appears below a button when the user hovers over it. The box should remain visible as long as the user's mouse ...