Reputation: 359
I found this awesome sliding animation on menu hover using jQuery, but i was wondering how i could make it so that when hovering for the first time it does not animate the left and width property but immediately jumps to the hovered item. After that, it does animate the background's position. Only when re-entering it again it will stop animating the first time.
// insert slider
$('ul').append('<div id="slider"></div>');
// initially reset
var left = $('ul li:first-child a').parent().position().left;
var width = $('ul li:first-child a').width();
$('#slider').css({'left' : left, 'width' : width});
// sliding
$('ul li a').hover(function(){
var left = $(this).parent().position().left;
var width = $(this).width();
$('#slider').stop().animate({
'left' : left,
'width' : width
});
});
Hope i explained this well enough...
Thanks in advance!
Here is the fiddle: http://jsfiddle.net/5wPQa/2/
Upvotes: 0
Views: 216
Reputation: 2064
Although this approach is a lot similar to 04FS's answer, I'll recommend you to go ahead with their solution as it dissolves redundant code.
$(document).ready(function() {
$('ul li a').hover(function() {
var a = $(this);
var left = a.parent().position().left;
var width = a.width();
var nav = a.parent().parent('ul');
if (!nav.find('#slider').length) {
nav.append('<div id="slider"></div>');
}
if (!nav.hasClass('animated')) {
$('#slider').css({
'left': left,
'width': width
});
nav.addClass('animated');
} else {
$('#slider').stop().animate({
'left': left,
'width': width
});
}
})
});
ul {
position: relative;
margin: 20px;
}
ul li {
display: inline-block;
}
ul li a {
padding: 5px 15px;
border: 1px solid #000;
color: #000;
text-decoration: none;
}
#slider {
position: absolute;
top: -5px;
left: 0;
height: 100%;
width: 0;
padding: 5px 15px;
margin-left: 1px;
background-color: #f00;
z-index: -1;
}
<script src="https://code.jquery.com/jquery.min.js"></script>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link number 2</a></li>
<li><a href="#">Link 3</a></li>
<li><a href="#">Link something 4</a></li>
<li><a href="#">Link 5</a></li>
</ul>
Upvotes: 1
Reputation: 5820
I’m assuming that you don’t want the first link to be highlighted by default then either? Then the // initially reset
part can be removed.
Let’s store the reference to the ul
element in $ul
, because we’re gonna need access to that element inside the link hover handler as well, and we don’t want to look it up in there every time using .parents()
or something like that.
Let’s add a class to the ul
right away, no-animation
. That is going to be used for two things, to hide the slider-div initially (via the stylesheet), and to determine whether or not we want to animate when the links get hovered.
Having the slider “jump” to a position instantly, instead of animating, can be done by simply calling .css()
instead of .animate()
- the rest of the code stays the same, so rather than repeating it, I’m gonna store the name of the method to execute in a variable, method
.
Now when the links get hovered, we check if the parent ul
has that class no-animation
first. If so, we remove that class, and set the method to css
instead of animate
.
$('#slider').stop()[method]()
then calls .css()
or .animate()
, depending on what method
contains.
And to reset the effect we simply add the class again, when the ul
itself gets un-hovered. That hides the slider-div again (due to rule in the stylesheet), and helps us determine that this is a “first hover” again next time.
// insert slider
var $ul = $('ul');
$ul.addClass('no-animation').append('<div id="slider"></div>');
$ul.on('mouseleave', function() {
$(this).addClass('no-animation')
});
// sliding
$('ul li a').hover(function() {
var left = $(this).parent().position().left;
var width = $(this).width();
var method = 'animate';
if ($ul.hasClass('no-animation')) {
$ul.removeClass('no-animation');
method = 'css';
}
$('#slider').stop()[method]({
'left': left,
'width': width
});
});
ul {
position: relative;
margin: 50px;
}
ul.no-animation #slider {
display: none;
}
ul li {
display: inline-block;
}
ul li a {
padding: 5px 15px;
border: 1px solid #000;
color: #000;
text-decoration: none;
}
#slider {
position: absolute;
top: -5px;
left: 0;
height: 100%;
width: 0;
padding: 5px 15px;
margin-left: 1px;
background-color: #f00;
z-index: -1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link number 2</a></li>
<li><a href="#">Link 3</a></li>
<li><a href="#">Link something 4</a></li>
<li><a href="#">Link 5</a></li>
</ul>
Upvotes: 3
Reputation: 28573
If I understand you correctly, and you want for the 'currently-selected' link to be highlighted on opening the page, you could add a "selected" class to your li and adjust the jquery slightly, to replace the "first-child" with your "selected" class. This would still work to slide to the other nav items, but would highlight your desired link first. (note: I first tried this with ":active" but it wasn't as successful)
See snippet (best viewed in "full screen" mode)
$('ul').append('<div id="slider"></div>');
// initially reset
var left = $('ul li.selected a').parent().position().left;
var width = $('ul li.selected a').width();
$('#slider').css({'left' : left, 'width' : width});
// sliding
$('ul li a').hover(function(){
var left = $(this).parent().position().left;
var width = $(this).width();
$('#slider').stop().animate({
'left' : left,
'width' : width
});
});
ul {
position:relative;
margin: 50px;
}
ul li {
display: inline-block;
}
ul li a {
padding: 5px 15px;
border: 1px solid #000;
color: #000;
text-decoration: none;
}
#slider {
position:absolute;
top: -5px;
left: 0;
height: 100%;
width: 0;
padding: 5px 15px;
margin-left: 1px;
background-color: #f00;
z-index:-1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link number 2</a></li>
<li class="selected"><a href="#">Link 3</a></li>
<li><a href="#">Link something 4</a></li>
<li><a href="#">Link 5</a></li>
</ul>
Edit: To remove the 'hover' but keep the sliding effect, change the 'hover' to 'click' in the jquery.
$('ul li a').click(function(){...
Hope this helps
Upvotes: 0