Alejandro Cordoba
Alejandro Cordoba

Reputation: 447

Lag on hover jQuery

Im doing a navbar that changes it icons when the user scrolls down (I'm doing this by changing the background of the div) in the same way, the background of the div has to change whenever the user hover over the icon, this is my code so far:

App.js

$(document).scroll(function () {
  scroll_pos = $(this).scrollTop();
  var h = $("#secOne").height() - ($("#secOne").height() / 10);
  if (scroll_pos > h) {
    $("#topBar").css({
      'padding': '2.5vh 7.5vw 1vh 7.5vw',
    });
    $("#menuIcon").css({
      'background': 'url("assets/menuBlue.svg") no-repeat',
    });
    $("#menuIcon").hover(function () {
      $(this).css('background', 'url("assets/menuBlueHover.svg") no-repeat')
    });
  } else {
    $("#topBar").css({
      'padding': '5vh 7.5vw 2vh 7.5vw',
    });
    $("#menuIcon").css({
      'background': 'url("assets/menu.svg") no-repeat',
    });
    $("#menuIcon").hover(function () {
      $(this).css('background', 'url("assets/menuHover.svg") no-repeat')
    });
  }
});

The problem is that the animation has a "lag" or it doesn't even change back the icon after the hover is done.

Any ideas how to change this?

Thanks for the help.

Upvotes: 0

Views: 234

Answers (1)

Dom Ramirez
Dom Ramirez

Reputation: 2212

You're having issues because you're applying a new "hover" event each time a "scroll" event is called. Up to hundreds of scroll events are called in the course of scrolling down a page, so up to hundreds of hover events are being called when you hover. The result is basically random and increasingly inefficient.

Since you asked the question with respect to your current code, I'll start with a direct answer, resolving the jQuery/Javascript logical issue. Then I'll suggest a "pure" css solution.

Fixing With jQuery (Sub-Optimal)

Try capturing the scroll position in a variable which is outside of your "scroll" event handler. Then also move your "hover" event handler outside of the scroll function. You can then use that scroll position variable to run your conditional inside of the "hover" function, updating the behavior each time a "hover" event is fired.

var scrolledPastH = false;

$(document).scroll(function () {
    scroll_pos = $(this).scrollTop();
    var h = $("#secOne").height() - ($("#secOne").height() / 10);
    scrolledPastH = scroll_pos > h;

    if (scrolledPastH) {
        $("#topBar").css({
            'padding': '2.5vh 7.5vw 1vh 7.5vw',
        });
        $("#menuIcon").css({
            'background': 'url("assets/menuBlue.svg") no-repeat',
        });
    } else {
        $("#topBar").css({
            'padding': '5vh 7.5vw 2vh 7.5vw',
        });
        $("#menuIcon").css({
            'background': 'url("assets/menu.svg") no-repeat',
        });
    }
});

$("#menuIcon").hover(function () {

    // This is the "handlerIn" function, passed as the first argument to .hover
    var background = scrolledPastH ? 'menuBlueHover.svg' : 'menuHover.svg';
    $(this).css('background', 'url("assets/' + background + '") no-repeat');

}, function () {

    // This is the "handlerOut" function, passed as the second argument to .hover
    var backgroundImg = scrolledPastH ? 'menuBlue.svg' : 'menu.svg';
    $(this).css('background', 'url("assets/' + backgroundImg + '") no-repeat');

});


Fixing With "Pure" CSS (Ideal)

As you can see from the above, manipulating appearance with jQuery/Javascript can require somewhat complicated code relative to simple UI treatments. "Pure" css enables you to forget about managing state as often.

Javascript/jQuery

$(document).scroll(function () {
    scroll_pos = $(this).scrollTop();
    var h = $("#secOne").height() - ($("#secOne").height() / 10);
    if (scroll_pos > h) {
        $("#topBar").addClass('scrolledPastH');
        $("#menuIcon").addClass('scrolledPastH');
    } else {
        $("#topBar").removeClass('scrolledPastH');
        $("#menuIcon").removeClass('scrolledPastH');
    }
});

CSS

#topBar {
    padding: 5vh 7.5vw 2vh 7.5vw;
}

#menuIcon {
    background: url("assets/menu.svg") no-repeat;
}

#menuIcon:hover {
    background: url("assets/menuHover.svg") no-repeat;
}

#topBar.scrolledPastH {
    padding: 2.5vh 7.5vw 1vh 7.5vw;
}

#menuIcon.scrolledPastH {
    background: url("assets/menuBlue.svg") no-repeat;
}

#menuIcon.scrolledPastH:hover {
    background: url("assets/menuBlueHover.svg") no-repeat;
}

Upvotes: 1

Related Questions