These “sliding” style navigation bars have been around a while, I just thought I’d take a crack at doing it myself as the opportunity came up recently. Turns out it’s really pretty darn easy. I put two examples together for it.
The Idea
The idea is to have a highlight of some kind (a background or an underline) follow you around as you mouse over the different links in the navigation. This will happen with jQuery and it’s animation abilities. As such, the “magic line” will only be appended via JavaScript. Once added to the list and styled, as you mouse over the different links, it figures out the left positioning and the width and animates to match.
HTML
Typical list here… It has the “group” class because it’s going to be a horizontal row and will need the clearfix so it has height. The ID is for the JavaScript to target it.
<nav class="nav-wrap">
<ul class="group" id="example-one">
<li class="current_page_item"><a href="#">Home</a></li>
<li><a href="#">Buy Tickets</a></li>
<li><a href="#">Group Sales</a></li>
<li><a href="#">Reviews</a></li>
<li><a href="#">The Show</a></li>
<li><a href="#">Videos</a></li>
<li><a href="#">Photos</a></li>
<li><a href="#">Magic Shop</a></li>
</ul>
</nav>
Notice the .nav-wrap div around it. That is used because of the styling, the bars go full width of the screen the but the navigation is centered within. This centering brings up an issue when we start the JavaScript.
CSS
Do the ol’ inline list elements with floated left anchors to get the list horizontal and avoid stairstepping. The magic line is absolutely positioned under the bar, so that it doesn’t cause jitter (mouse over a link, animates over, mouse is now on magic line not the link, animates back, etc.) Everything else is purely stylistic.
.nav-wrap { margin: 50px auto; background-color: rgba(0, 0, 0, 0.6); border-top: 2px solid white; border-bottom: 2px solid white; }
#example-one { margin: 0 auto; list-style: none; position: relative; width: 960px; }
#example-one li { display: inline; }
#example-one li a { color: #bbb; font-size: 14px; display: block; float: left; padding: 6px 10px 4px 10px; text-decoration: none; text-transform: uppercase; }
#example-one li a:hover { color: white; }
#magic-line { position: absolute; bottom: -2px; left: 0; width: 100px; height: 2px; background: #fe4902; }
jQuery JavaScript
- When DOM is ready…
- Set up variables including current left offset of the navigation
- Set up resize function on the window to reset that offset should it change (because of the centering)
- Append the magic line to the nav
- Set up position and width of the magic line for the current page item
- Also set the original width and position as data, so it can be used to animate back to
- On hover, calculate the new width and new left position and animate to it
- On the hover callback (mouse out), animate back to original
Updated, thanks to smart comments by Daniel and Nora Brown below.
$(function() {
var $el, leftPos, newWidth,
$mainNav = $("#example-one");
$mainNav.append("<li id='magic-line'></li>");
var $magicLine = $("#magic-line");
$magicLine
.width($(".current_page_item").width())
.css("left", $(".current_page_item a").position().left)
.data("origLeft", $magicLine.position().left)
.data("origWidth", $magicLine.width());
$("#example-one li a").hover(function() {
$el = $(this);
leftPos = $el.position().left;
newWidth = $el.parent().width();
$magicLine.stop().animate({
left: leftPos,
width: newWidth
});
}, function() {
$magicLine.stop().animate({
left: $magicLine.data("origLeft"),
width: $magicLine.data("origWidth")
});
});
});
Demo
See the Pen
jQuery MagicLine by Chris Coyier (@chriscoyier)
on CodePen.
Issues
Opera is weird about it. It makes the original width of the magic line the full width of the nav bar and shortens it from the right on hovers. I haven’t been able to figure it out. If you do, awesome, let me know I’ll update this article and demos.
Alternate Version
Check out the demo link below for an alternate version that uses a background instead of a line, and animates color as well as position and width. Basically the same, except the CSS is slightly different and the JavaScript pulls the color of the new list item from a rel attribute in the HTML.
Color animations in jQuery require the color plugin. I was just moaning about how it doesn’t work with RGBa color, and someone sent me a patch that does, which is included in the download. I’m really sorry, but I can’t remember their name! Speak up if it was you and I’ll update this and credit the patch to you.
All Yours
As always, feel free to do whatever you want with it. Preferably, use it in corporate projects and earn wheelbarrows of cash.
nothing new man…
Hi Chris,
You make this stuff so simple – thanks for all your great tips and hard work! My question is can this work with multi-level navigation as well? It wouldn’t need to apply the effect the the child links, but would like to be able to have them drop down. Any tips on this is helpful.
Thanks, Larry
Larry just asked the same question that I had as well. This is a great start, but what needs to happen to support multi-level navigation?
Though I haven’t tried it myself, one thing that might work is duplicate the code for the find(“a”) hover and make one for $(“li:not(:has(ul))”). that does the default stuff (it doesn’t have a UL-child so it’s not a dropdown-able item)
And another one for $(“li:has(ul)”) that does have a ul-child. In that case move the magic line horizontally where it should be, but also move it down the height of the UL-element.
If you dont want the magic line to move diagonally (ie. shortest route) then you need to queue the animation to go horizontal first to the LI-item, and then move vertically down (position: absolute; bottom: -(2 + UL-height)px; ). And on MouseOut (callback of hover() – move vertically up and then horizontally).
I might try this next weekend, but I’m not sure I’ll remember. Feel free to see if it works out !
—
TeMc
Try looking into the dropdowns (also jQuery based):
Thanks for sharing Chris, just a little detail. Download is broken.
Once again, a sly implementation!
As always, feel free to do whatever you want with it. Preferably, use it in corporate projects and earn wheelbarrows of cash.
Yes sir!
Actually, I needed this for a commercial project as it was, and this just satisfied that need. You’re a 5-star helpful guy :)
Wow, simply effect that looks pretty good.
Just one thing, i prefer to have the magic-line li in the html markup, instead of appending it by javascript.
Its just a matter of taste and probably your way is better for seo, but as a developer i love to see exactly the markup i’ll have to work with ;)
Daniele,
I am having the exact same problem… have you gotten it fixed?
How would you use this with WordPress’ wp_page_menu?
Just what I was looking for today. I like the way you set up all your links to previous examples. I hadn’t checked out your clearfix or stairstepping pages. This was a great way to look at them within a specific context. Thanks agiain, Chris!
Is anyone else seeing problems in IE8? The class “current_page_item” color is not working onLoad. I’ve tried setting the color inline and it still doesn’t work. I’m pretty sure it’s a JQuery issue which I don’t know well enough to fix.
hi I see the same, pls email me if a solution is provided
wow, this effect looks really nice and at the same time is very subtle. great work! many thanks for sharing it!
as always, your work is brillant, yet easy to understand and implement. thanks.
Really nice effect, can’t say i’ve seen it used that often, or i’m just not paying attention to the sites that do use it!
I have had a look through all the browsers and IE8 is a little funny with it, i’m gunna play around with it tonight and see whats up. As far as opera is concerned… that’s all i have to say on that.
Very nicely Done Chris! This will be very useful for sites that don’t need dropdowns.
Thank you Chris love it!
Great article and nice effect Chris!
The whole pageOffset thingy isn’t really necessary though. If you use jquery’s position() method you can simply replace e.g.
with:
I tried it myself and it works just as good
Thanks Daniel, great idea, I updated the above code, demo, and download.
This is Sexy nav for sure!!! Thanks Chris!!
Hi Chris this is really cool. Is jQuery killing Flash menus? or Animation? I think so.
There is a very little thing I wanted to Know and I it would be interesting, is it possible to make the magic line stop at the last item on the menu that I clicked?
On the list item there is a class (class=”current_page_item”) that makes the line stop on that spot. So for each page that you click on just change the class to that link and the line stops on that link.
$(“#example-one li a”).hover(function() {
$el = $(this);
leftPos = $el.position().left;
newWidth = $el.parent().width();
$magicLine.stop().animate({
left: leftPos,
width: newWidth
});
}, function() {
$magicLine.stop().animate({
left: $magicLine.data(“origLeft”),
width: $magicLine.data(“origWidth”)
});
});
here magic line is moved back to original position with below function from above code , so u can move that function from code and it works.
function() {
$magicLine.stop().animate({
left: $magicLine.data(“origLeft”),
width: $magicLine.data(“origWidth”)
});
I first viewed it in Opera and thought “awesome”!! I didn’t even realize it was broken in Opera. That just proves (to me at least) that it can look radically different in different browsers, and that’s ok.
I haven’t attempted any debugging, but there’s the strangest thing… Remove the first example from your demo file and the second example stops working. (Unless I did something terribly wrong — which I don’t think I did.)
There are some variables set up above /* Example One */ in the JS, make sure those are still there.
Still trying to work with it am having the same problems and am trying to learn all this how can do remove the upper please and still make it work lol
am a very new guy to type of work and would like to add this style to me new web build for my site.
cheers Jason
Just curious if this:
is better (faster?) than
?
Really nice demo – I like these subtle effects you can achieve pretty quickly and simply with jquery.
Nope probably not, that’s a blunder on my part. It was original there because I needed to use a .not() filter on some of the list items, but still target the anchor links, hence the .find(). Feel free to write it your way.
Just added it to a client’s site, Thanks Chris.
DUDE U THA BOMB!!!!
One hell of a trick, nice man. Thanks
Great Tutorial. Thanks For Sharing!!
I love the last one
just put something simmilar into effect on a recent project of mine:
here
although I used the lava lamp jquery script
Prior art:
http://devthought.com/blog/projects-news/2007/01/cssjavascript-true-power-fancy-menu/
which inspired for jQuery:
http://www.gmarwaha.com/blog/?p=7
Nice article nonetheless.
Hmmm.. this is nice. Another thing to play with.
Been playing a little with it in Opera. Getting the width from the anchor instead of the parent listitem almost fixes it… (Now the problem is that it is a bit too narrow.) Tried tweaking the css to fix that but didn’t quite work either.
Seems the problem is that .width() of an inline listitem doesn’t work right.
Reverted my changes and rather changed the css to use inline-block like this:
#example-one li { display: inline-block; }
That works perfectly. (in Opera at least. :)
Chris, great job with this plugin… you’ve taken the Lava Lamp treatment and made it your own. And designed a nice demo page in the process.
Thks for idea. It’s col
I’m loving this menu, but finding it very frustrating trying to add sub menus. Has anyone mastered this 2nd part and added sub menus or can point me in the right direction? I’m not a JS guru, so just pointing me to code doesn’t help much, though I’m not a total nitwit when it comes to coding. Any and all help would be appreciated.
Great!
Can improve it a bit with a click() function to make Magicline staying over clicked link :
Indeed, thanks pintus. The “current_page_item” thing is the default WordPress class name applied when using wp_list_pages, so when a new page loads it would have that and be set correctly. But if using some kind of AJAX or whatever instead, use this.
OOps sorry I didn’t know I’ve never tried WordPress…
I use Ajax and i tried to use your code to make Magicline staying over clicked link but it don’t works.
Do I have to change something on the htlm page?
Where do I have to put your code?
Thanks a lot!!
Ok ok i just find my error ^^
Sorry for double posting
For some reason I can’t get the line to stay on the link it is supposed to be on. It stays there right after I click it, but goes back to home when the new page loads. How do I get it to stay put?
Thanks
Sorry I split my code…
just paste both parts!
So i am having trouble making this work with wordpress. Works on the homepage but if I go to any other page it fails to work and also never remembers the new page.
Help :)
Chris, this fixes Opera and works in all browsers I tested (FF3.6, Chrome, IE8, Opera 10.10 and Safari, all running under WinXP). I only listed the lines I changed:
Basically, I floated the <li>'s instead of the <a>'s, and then I had to adjust the padding on several elements to make everything look right.
This fixes bug in IE7 where current link text was missing. Thanks.
That’s so simple and sweet. Thanks for sharing! :)
anyone else not able to get it to stop on the item you last clicked on? the above method doesnt seem to work for me
Hi, I combined this great script with a vertical submenu…
http://www.castellolarocchetta.it/test/
is there a way to make the magic line (i changed it into a little logo) to stay in the original position (current_page_item) instead of moving to the left of the navbar when going on a submenu link? thank you for your great work
It looks like the second example doesn’t work for any version of IE. I haven’t gone through the code yet – but has anyone else been noticing this?
There is a problem in the jquery.color-RGBa-patch.js code. It’s trying to assign an rgba() value, which IE doesn’t recognize, to the magic line element’s background.
Yep I’m sure that’s what it is. Just make none of the color values RGBa and you should be OK.
Just went to look at this, and it’s already solved. Glad I checked back here. Thanks for the help!
Hi Chris, your all tutorials are really awesome. I’ve learnt a lot about CSS and jQuery by just watching and reading ur all articles. They really helped me lot.
While I’ve a query. Actually I wanna know how u have made this comment system ?
I mean to say each person can reply to one another too. While the comment box has a very nice feature like, it is showing what to put in the box, and when we mouse over it, it just grayed out but didn’t vanished totally, but when we put our name then it vanishes.
Can u write an article on this subject ? It will be really helpful for me and like me, who are beginner.
This tutorial rock. Thank you.
set the textarea of this comment “resize” property to “vertical” so when resize it much more good than this
Hey Chris! I was looking at doing something like this just last week! I’m going to give it another shot with this method and try use it for a WordPress theme I’m working on, I’ll try to add the dropdowns too and let you know how I go. Your blog is fast becoming my favorite reference spot for this kinda thing.. cheers :)
Hi! Very great demo. Happy to use on a my client project. I made some test on and I have some trouble under win xp with explorer..Somebosy could help me?
Cheers:)
I ve used html very badly.Sry. U can see the demo as well :)
Hey chris, I didn’t read through all of the comments to see if this was here but i downloaded this and it’s not working in opera, at least not very well.
well that was pointless i scrolled up and bam! there was the solution^^ srry
Hi Chris i need still help for IE.
http://ekolor.sitiweblecce.it
I made the changes written up but still doesn’t work.
Thx:)
I am seeing the same issue in IE8 too. Any ideas Chris or anyone how to fix this? plz…
Hi, great script, thanks – but is there a way to put a slight delay on the magicline movement?
Chris
Hi Chris I’m great fan of your work. Thanks for sharing all such code piece.
Hey Chris,
thx for the inspiration again =), the underline-thing in example 1 is great…
I use this Plugin for several months on different projects and I’m sure this effect could also be achieved with it…the jQuery Code is heavier I think but it really works with all browsers and has very useful additional features…
Nice effect, i like JQuery. Thanks for sharing
Great code!!
Do you know of a way to make it go vertical rather than horizontal?
I get example2 working in IE with adding a browser detection in your example.js. After “$(function(){” you can add something like:
In the html you have to add the id=”nav1″ ..
I also made the changes in the css from John Pisello.
Hi Haichen, tried to make your tips. I’m using example ttwo too, applied changes from John P. too, but i still have problems with I.E.
Site url is ekolor.sitiweblecce.it
I paste the code too :
HTML
EXAMLE.JS
No changes…
Thx a lot for your help
If you first load the site you get a “wrong” color. In example.js add the background line to change it.
Thnks Chris. Very useful javascript menu. But it is not perfect in the Ie 6. And i have fix the error. I have used In my menu the jpg image like pointed arrow at the bottom of the menu.
The page loading in Ie6 the ” magic-line” div is positioned on the middle of the menu text.
Who cares about IE6? It’s a 9 year old browser.
I’ve stopped supporting that browser all together, as should everyone. :)
hi!
very nice article.
is there a way to completely hide the red bar when none of the page is current?
I mean there are some pages on my app that can’t be reached clicking on the menu.
When the user is there, the red line should disapper if she is not hovering on the menu.
any idea?
thanks!
I try it again:
Hi Alfredo,
The id belongs to your links. They have to look like this:
As you can see the links have rgb as standard. If the Browser isn’t IE jquery makes rgba. So Transparency is only for non-IE.
please delete my previous post
thx
Thx Haichen:)
Made the changes but still not working..
Have patience;)
I paste js code to show u :
Thx a lot
Regards,
Alfredo
in your css you’ve to put a fallback for the rgba.
Put both definitions in the css.
and this:
IE takes the rgb and most others the rgba.
and there are two #nav1, but that seems to be no problem.
tried this with your code and it worked in IE.
hopefully this wil help.
Thx Master!:))Now all runs fine.U have given me a big help.Thx a lot:)
Regards,
Alfredo
I’ve added one more point (“wrong” color) accidently some comments above, but maybe you’ve seen it.
haichen
:-)
Hi!
I had the problem in Opera but I changed “display:inline” for “float:left” and it worked.
My HTML code is a bit different so I paste here:
HTML
And the CSS:
The js is the same.
Thanks!
hi! Anyone got example 1 working on IE? thanks
Thanks for sharing this article . I will used your code apply to my project.
Is there any possibility to make the menu switch while using other links? For example, I have “news” page on my site (news.html); and I want menu not only to change while I’m pressing news link from the menu, but also casual news link from the main site body. Another problem is that i use IFRAME as main site body. I thought I need something like this:
This is code inside the IFRAME body; also I have this:
in the main index page code.
But it doesen’t work. Note that if I use and alert(‘parent.document.getElementById(‘a1′).className’); I got normally printed message with text “testclass”.
Probably I have to trigger some additional functionality of the example.js script? How I can do this?
That’s ridiculously slick. Geez, I want to tear apart my own site now just to implement this style of navigation. Thanks for sharing!!!
Great peice of coding, it’s a massive help to have a CSS jQuery based nav rather than a nasty Flash one!
Well done Chris!
I’m having issues with this in IE8..
It works in all other browsers that I’ve tested..
In IE.. when you hover over the link and then mouse out, the line runs away :P
It goes clear off the page to the right.. creates a horizontal scrollbar.. Ideas?
Could this not have been done with a CSS:hover class?
Awesome menu! I have a contact section and would like the button separted so that it displays on the right. Is this possible? Ive added
.right_page_item a { float: right; color: white !important; }
to the css and the webpage, but still no go
Hi,
Great tutorial.
I had an issue with IE8 in standards mode (was fine in compatibility view though)- getting the initial width of the current_page_item, which actually blanked that item out until I hovered over it. Not great. Seems there’s an issue with getting the width of an inline element in IE8 (although the bug didn’t happen when getting newWidth when hovering over a new item – weird eh?).
Changing the CSS of the following
#example-one li { display: inline; }
into
#example-one li { display: inline-block; }
solves the problem though. It looks like it solves the Opera issue you mention in your tutorial as well!
Keep up the great work.
Thanks for the idea and tutorial! I implemented it on my blog with a slight modification. There is an overline and an underline in my theme.
I have a problem:
I want to use the 2nd example of MagicLine, but if I implement jQuery 1.8.3 (I need for fancybox) the color doesn’t change anymore :(
how will it work when it active on a page.
It works like this: http://www.ministranten.stvitus.de/new/
I would to add an active when it click or the highlighted menu but how?
That’s my question :/
Has somebody found a solution for the sub menu problem? maybe a little demo or something? please!!! :)
Sorry but there is an error in the JavaScript code:
leftPos = $el.position().left;
should be
leftPos = $el.parent().position().left;
And many thanks for sharing this.
And forgot to mention also this error:
.css("left", $("li.current_page_item a").position().left)
should be
.css("left", $("li.current_page_item").position().left)
All this because if you refer to the ‘a’ tag position(), it is ; and will return ; always 0 (zero)
Thanks again
What would be the mod to activate the animation on click only? I changed the .hover event to a .click event
$("#example-one li").find("a").click(function() {
but of course you get a flash of the red beneath the selection before the animation can take place. How can I avoid this flash?You know what, I totally botched that. the .click works perfectly, I had redundantly added a second animate function to the script. I love this plug-in even more now!
This was almost exactly what I was looking for!
Had to use this for a client and made the following edits:
line above only
line had to be only as wide as the link
line couldn’t jump back when mousing between anchors
current_page_item had to stay same color when :hover, but others had to change on :hover
check the fiddle:
http://jsfiddle.net/alexwcoleman/Dwv7X/
(my jquery/javascript is not strong, so if any suggestions…)
Hello,
I want to use this MagicLine for a vertical navigation. So i got the question: can the magic line work vertically instead of horzionatally? Or is there any tutorial for that ?
I am trying to update the plugin to use on a site that employs JQuery 1.9 or 2.0 . Does anyone know off-hand which of the contained functions have been deprecated/replaced in the js?
Hi
Thanks for all beautiful things.
One problem i am facing when i am applying position:relative to li tag. This is not working.
I had to add
position:relative
to the#example-one li a
to actually see the magic-line behind links, without it it was over them, as it was ignoring the z-index settingsHi,
I’m not a coder, but am usually competent enough to adapt code for my needs, and usually can figure out my own implementations with research. In this case, I’m hitting the wall.
I don’t know if anyone can help me. I’m trying to use this on a site I’m building out on squarespace. I’ve done jquery addon’s plenty of times, but can’t get this one working. I’ve altered the script to reflect my templates classes and ID’s, and tested it using a code block I stuck in the middle of my page. But for whatever reason I can’t get it to work with the actual menu at the top of the screen.
I feel like the portion of the code that finds the hover over areas over the links aren’t seeing the curser because of something in the templates CSS. Any help would be GREATLY appreciated. You can see the page at
http://boxjelly.squarespace.com
&
$(“.cf li a”).hover(function() {
Should finding portion of the code be drilled down more? i.e.
$(“.desktopnav nav.main-Nav div.nav-wrapper ul.cf li a…
I don’t know if that makes any sense
-Matt
Oh, and this is the full code I’m using + the CSS
$(function() {
});
//Magic Line
//.cf { margin: 0 auto; list-style: none; position: relative; }
//.cf li { display: inline; }
//.cf li a { color: #bbb; font-size: 14px; display: block; float: left; text-decoration: none; text-transform: uppercase; }
//.cf li a:hover { color: white; }
#magic-line { position: absolute; bottom: -2px; left: 0; width: 100px; height: 2px; background: #fe4902; }
I’ve commented out most of the style elements since the navigation menu already has style elements applied to it.