简体   繁体   中英

Using jQuery to change icon on hover

I am trying to use jQuery to make my icons change on mouseover . With Semantic UI, some/most icons can be different if you add "outline" as a class. For example: <i class="icon user"></i> and <i class="icon user outline"></i> .

My idea is to simply toggle the class outline with jQuery on mouseover , but then I run into a few problems:

  1. Because the a within nav is selected, if you hover over the li inside a , the function will run again. It should only work if you hover over the whole a .

  2. It changes all my icons in the navigation dropdown, and not just the one I am hovering on.

  3. The effect stays there even when I move my cursor away, and only goes away once I hover over the element again. (perhaps add a mouseout ?)

  4. The "home" icon does not have an outline version, so it should not be affected.

I hope the idea is clear.

JSFiddle

HTML

<nav class="smallNav">
  <ul>
    <a href="#">
      <li><i class="icon home"></i>Home</li>
    </a>
    <a href="#">
      <li><i class="icon star outline"></i>Featured</li>
    </a>
    <a href="#">
      <li><i class="icon newspaper outline"></i>News</li>
    </a>
    <a href="#">
      <li><i class="icon user outline"></i>Career</li>
    </a>
    <a href="#">
      <li><i class="icon envelope outline"></i>Contact</li>
    </a>
  </ul>
</nav>

jQuery

$('nav a').mouseover(function() {
  $('nav i').toggleClass('outline');
})

Use hover() instead of mouseover() :

$('nav li').hover(
 (e) => $('i', e.target).toggleClass('outline')
);

The above code runs the same function on both mouseover and mouseout event. If you want to run different functions on each, provide the one for mouseout as the second param. Otherwise, the one from mouseover is ran on mouseout , too.

Also, I limited it to the hovered item only: $('i', e.target) => i elements inside e.target , which is the hovered element. See it in action:

 $('nav li').hover( (e) => $('i', e.target).addClass('outline'), (e) => $('i', e.target).removeClass('outline') ) 
 .outline { border: 1px solid red; } i { width: 1rem; height: 1rem; display: inline-block; box-sizing: border-box; margin-right: .5rem } li, ul { list-style-type: none; margin: 0; padding: 0; } ul { display: flex; flex-direction: column; max-width: 150px; } li { display: inline-block; } li:hover { background-color: #f5f5f5; display: block; cursor: pointer; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <nav class="smallNav"> <ul> <li><a href="#"> <i class="icon home"></i>Home </a></li> <li><a href="#"> <i class="icon star"></i>Featured </a></li> <li><a href="#"> <i class="icon newspaper"></i>News </a></li> <li><a href="#"> <i class="icon user"></i>Career </a></li> <li><a href="#"> <i class="icon envelope"></i>Contact </a></li> </ul> </nav> 


Important : your current markup is invalid. The only legal direct children of <ul> elements are <li> elements.

Note : even though hover(toggleClass) is short, you'll find sometimes one or more elements can get bugged out by missing a mouseover or mouseout event, at which point it will start working inversed. To prevent that, you should stick to the verbose form:

$('nav li').hover(
  (e) => $('i', e.target).addClass('outline'),
  (e) => $('i', e.target).removeClass('outline')
)
$('nav a').hover(function() {
    if (!$(this).find("i").hasClass("home")) {
    $(this).find("i").toggleClass('outline');
  }
})

Edit: Changed the method to hover

It toggle the class only for the <i> that is child of that specific <a> , and only if it doesn't have the home class

This could give you a bit more control:

function a(e){
   $(e.target).addClass("outline");
}
function b(e){
   $(e.target).removeClass("outline");
}

$("nav a").on("mouseenter", a);
$("nav a").on("mouseleave", b);

(not tested)

Obviously, you can adjust a/b method to remove/add class as necessary.

I'd think you'd be better off doing this with pure CSS instead of javascript.

.icon.home{
     height: 50px;
     width: 50px;
     background-image: url(path_to_image);
     background-repeat: no-repeat;
}

.icon.home:hover{
     background-image: url(path_to_hover_image);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM