1

I need to add css class .hovered on html element when hover, for this I created a small example snippet below. It has couple of issues.

When I hover on a child element it shouldn't add .hovered class to its parents, for example in below snippet, a inside nav element, it shouldn't add border to it's parent (nav).

But most importantly, I need to select elements in DOM dynamically, so instead this $( "div,nav,h1,h5,p,a,button") I would like to provide something like $( "*"), so I would be able to hover on any kind of element.

$(document).ready(function(){
    $( "div,nav,h1,h5,p,a,button")
  .mouseenter(function() {
    $( this ).addClass("hovered");
  })
  .mouseleave(function() {
    $( this ).removeClass("hovered");

  });
});
.hovered {
  border: 2px solid red;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>

<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
  <h5 class="my-0 mr-md-auto font-weight-normal">Company name</h5>
  <nav class="my-2 my-md-0 mr-md-3">
    <a class="p-2 text-dark" href="#">Features</a>
    <a class="p-2 text-dark" href="#">Enterprise</a>
    <a class="p-2 text-dark" href="#">Support</a>
    <a class="p-2 text-dark" href="#">Pricing</a>
  </nav>
  <button>Sign up</button>
</div>

<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
  <h1 class="display-4">Title</h1>
  <p class="lead">paragrpah</p>
</div>

How could I achieve it with vanilla JavaScript or jQuery?

FluffyKitten
  • 12,639
  • 10
  • 31
  • 45
user969068
  • 2,446
  • 4
  • 30
  • 55
  • You can select any element by using the wildcard exactly as you wrote it - $("*").onMouseEnter.... But this is probably not a great idea, because it will be slow. If I understand your question, you are asking how to apply a global mouseEnter to every element on your page, and only have the element you actually hovered on be outline - for that, you should investigate event bubbling and use event.stopPropagation to prevent this. – Toby Sep 09 '20 at 16:37
  • https://stackoverflow.com/questions/14646790/how-to-disable-parent-hover-when-hovering-over-child – brk Sep 09 '20 at 16:40

3 Answers3

1

I'm not sure how efficient doing what you want can be, as you want to run this for every element on every mouse action. But if you really want to, you can do it like this:

$("*").not("body,html")
   .mouseenter(function() {
        e.stopPropagation();
        $(this).addClass("hovered");
        $(this).parent().removeClass("hovered");
    })
    .mouseleave(function() {
        $(this).removeClass("hovered");
    });
});

How this works:

  • Select all elements except body and html
  • On mouse over of an element: Add the class to the hovered element and Remove the class from the parent element

Remember that when an element is hovered, it's parent (and its parent's parent etc) are also hovered, so this is why we need to remove the class from the parent.

Working Example:

$(document).ready(function() {
  $("*").not("body,html")
    .mouseenter(function() {
    console.log($(this));
      $(this).addClass("hovered");
      $(this).parent().removeClass("hovered");
    })
    .mouseleave(function() {
      $(this).removeClass("hovered");

    });
});
.hovered {
  border: 2px solid red;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />

<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
  <h5 class="my-0 mr-md-auto font-weight-normal">Company name</h5>
  <nav class="my-2 my-md-0 mr-md-3 p-2">
    <a class="p-2 text-dark" href="#">Features</a><a class="p-2 text-dark" href="#">Enterprise</a><a class="p-2 text-dark" href="#">Support</a><a class="p-2 text-dark" href="#">Pricing</a>
  </nav>
  <button>Sign up</button>
</div>

<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
  <h1 class="display-4">Title</h1>
  <p class="lead">paragrpah</p>
</div>

Update: The 2 issues you mention are to do with your HTML. You can fix them as follows:

  1. Hovering a menu item outside the text can also outline the nav:
    Your nav element isn't fully containing your menu items - they are extending outside the nav boundary because you added p-2 to them. Adding p-2 to the nav will make the hover work as expected.
  2. Nothing is outlined when hovering between menu items:
    White space doesn't trigger a hover event, and your a elements are separated with white space (a linebreak, tab or space will do this). You can delete the white space from between the a elements like this - it's a bit of a hack but it works:
     <a href="#">Option 1</a><a class=href="#">Option 2</a>...

These are fixed in the working example above if you try it now

FluffyKitten
  • 12,639
  • 10
  • 31
  • 45
  • Thanks @FluffyKitten , It is close to what I am looking to achieve but it has couple of issues, 1. when mouse is on any menu item inside `nav,` it is adding border to nav also. 2. when mouse is in middle of "Features" and "Enterprise" elements, it should add border around nav. – user969068 Sep 09 '20 at 16:46
  • @user969068 I've updated my answer to explain why this is happening and how to fix it, and updated the code example too if you'd like to try it again. – FluffyKitten Sep 09 '20 at 16:58
  • actually I don't have control over HTML, so, With above It could work if I will process html in backend before handing over to this snippet. I will accept your answer as it did solve 90% of issue, I will update if I found more robust solution which doesn't require cleaning html. Thanks – user969068 Sep 09 '20 at 17:37
  • @user969068 Hovering over a white space simply doesn't trigger a hover event in the browser which is the event you are trying to capture, so there isn't really any other way around that other than find a way to remove it I'm afraid! Its such a tiny space where it happened that you might want to consider if it makes a significant enough difference to warrant the extra processing. But glad I could help anyway! – FluffyKitten Sep 09 '20 at 17:40
0

In Javascript you could do something like below:

You can get element by there tagName's(like div, h1) and get them by getElementsByTagName or you can add classes to these element and get by getElementsByClassName

document.addEventListener('DOMContentLoaded',  function () {
   document.getElementsByTagName('div')[0].addEventListener("mouseover", 
     function(e) {
        e.target.classList.add("hovered");
   });
    
   document.getElementsByTagName('div')[0].addEventListener("mouseout", 
   function(e) 
    { 
        e.target.classList.remove("hovered");
    });
});

Dolly
  • 1,081
  • 4
  • 24
0

You probably don't need Js here.

CSS-only solution:

div:hover, div *:hover {
  border: 2px solid red;
  cursor: pointer;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>

<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
  <h5 class="my-0 mr-md-auto font-weight-normal">Company name</h5>
  <nav class="my-2 my-md-0 mr-md-3">
    <a class="p-2 text-dark" href="#">Features</a>
    <a class="p-2 text-dark" href="#">Enterprise</a>
    <a class="p-2 text-dark" href="#">Support</a>
    <a class="p-2 text-dark" href="#">Pricing</a>
  </nav>
  <button>Sign up</button>
</div>

<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
  <h1 class="display-4">Title</h1>
  <p class="lead">paragrpah</p>
</div>
Kosh
  • 14,657
  • 2
  • 15
  • 31
  • Thank you @Kosh but It is not what I need, It adds border to everything, I need border only at hovered element. please see FluffyKitten answer and my comment on his answer – user969068 Sep 09 '20 at 16:49