secondary fixed navigation
August 25, 2014 | 43 Feedbacks

Secondary Fixed Navigation

A secondary navigation intended for users who want a quick overview of the page content, and be able to easily move from one section of the page to the other.
Browser support
  • ie
  • Chrome
  • Firefox
  • Safari
  • Opera

A fixed navigation with smooth, jQuery powered scroll. Nothing fancy here, yet a handy snippet for creating a secondary menu to quickly surf through the page content. We see this effect a lot these days, a good example I can think of is Disqus For Websites. A nice touch is to animate the logo and the main call-to-action button to slide in once the navigation becomes fixed.

Creating the structure

We created a section#cd-intro to wrap our intro image, tagline and call-to-action button.
The secondary navigation is an unordered list inserted in the .cd-secondary-nav element. All the remaining content has been placed in the .cd-main-content element.

Adding style

Since we coded this resource starting from mobile, we assigned a position: fixed to the unordered list inside the .cd-secondary-nav, and placed it at the bottom-right of the viewport. When user taps the .cd-secondary-nav-trigger, we assign the class .is-visible to the unordered list, changing its CSS3 Scale value from 0 to 1.
When the viewport is larger that 1170px, we hide the .cd-secondary-nav-trigger and change the position of the unordered list from fixed to static, so that it is visible inside the .cd-secondary-nav, right after the section#cd-intro.

When the user scrolls more than the section#cd-intro height, we assign the .is-fixed class to the .cd-secondary-nav, changing its position from relative to fixed and reducing its height, and then we add the .animate-children class to animate its children. We couldn’t use a single class due to a Firefox bug (CSS transition animation fails when parent element changes position attribute). More info about this in the Events handling section below.

We also wanted to show the logo and the call-to-action button when the secondary navigation is fixed. To do so we defined two classes: .is-hidden and .slide-in (the first is assigned when user scrolls more than the #cd-intro-tagline bottom, the second more that .cd-secondary-nav top).

Events Handling

When user scrolls more than the secondary navigation offset top, we assign it the .is-fixed class to change its position value; we add the .animate-children class with a 50ms delay (due to a Firefox bug) in order to animate its children. Therefore the position value change won’t affect the transition, since the they don’t happen at the same time.


Aug 25, 2014
  • Resource released by CodyHouse

Claudia Romano

Web developer, fan of The Big Bang Theory and good food. Co-founder of CodyHouse and Nucleo. You can follow her on Twitter.

  • Sergey Dubovik

    Interesting approach. But animation of disappearing icons is a bit slaggy. Maybe it worth a try to use <-Skrollr or something similar

    • Claudia Romano

      Hey Sergey, thanks for the heads up. Could you please tell me which browser/version are you using? We have been testing the animation and it seems smooth. Thanks!

  • Tomasz Stryjewski

    nice article!

    however, there are few things i’d like to point out:
    1. i don’t like the inconsistency with selectors: secondaryNav is cached, while $(window), $('#cd-logo') and $('.cd-btn') is not – any reason for that?
    2. I think it would make sense to debounce whole scroll handler, since $(window).scrollTop() will trigger layout and can potentially cause a “jank”
    3. there is setTimeout(), which is not cached and canceled, if the next one occurs – this POTENTIALLY could cause a queue of async actions happening (hope I explained it well… if not, please let me know)

    please, don’t take it as an insult of any kind :-)

    • Claudia Romano

      Hi Tomasz, thanks for your comment! Not at all, actually these are the kind of comments which helps us improving our resources, so always appreciated! :)

      1. I usually cache the variables which are used not only for adding/removing classes. But, of course, it’s possible to create other variables and store the other selectors;

      2. Totally agreed on that. We didn’t use it because we only add/remove classes inside the scroll event; but as you wrote, it’s a good practice and the whole code could be wrapped ,e.g., in a requestAnimationFrame();

      3. We used setTimeout() (not setInterval() ) so that the function is executed only once (we used it to fix a Firefox bug).

      Hope I was clear! :) Cheers

      • Tomasz Stryjewski

        fir this, i’ll use to be more precise in my answers :-)

        re 2. not even that – what i meant was that you should DELAY the execution of the function after the scroll has been paused for a little amount of time (see ) – look @ file 1_debounce.js in the gist

        re 3. i didn’t mean you should use setInterval(), but that you should cancel the previous timeout, if it’s still present, like in 2_clear-timeout.js in the gist

        i also provided 3_combined.js to combine both of those.

        let me know if something needs more explanation :-)

        • Claudia Romano

          Hey Tomasz,

          re 2. I think we are saying the same thing (the requestAnimationFrame() API does the same job, but the delay is ‘decided’ by the browser );

          re 3. My point is : we have been using the setTimeout() so that the function is executed only once. And since we didn’t want to prevent it from being executed, we didn’t need to use the clearInterval(). But of course there’s no harm in adding it.

          • Tomasz Stryjewski

            re 3. here you are mistaken… it will be executed X times, where X = amount of scroll events. demo:,output

            open up the console and check scrolling on both boxes – the 1st one uses your technique, while the 2nd one uses the “debounced” one

  • AT80®

    Always fresh and new.. Keep up the hard work.. Love it.

  • TheWeekend1

    Awesome stuff.

    Could you please tell me which icon pack you used? Or are they custom? :c

    • Claudia Romano

      Glad you liked it! They are custom ;)

  • Mark Henry Gremmen

    Would be cool of it could scroll one page (section) at the time for the secondary navigation.

  • Peter Steintjes

    Thanx for this great looking navigation. I have a problem which I am trying to solve for quite some time but I can’t manage to solve it. Maybe someone is willing to help me out. I try to integrate this navigation into alternate-fixed-scroll-background and when I try to link a page to a button for example intro, location etc, firebug shows a message: TypeError: target.offset(…) is undefined. I tried to replace “#cd-placeholder-1″ to “cd-scrolling-bg cd-color-2″ or “#cd-scrolling-bg cd-color-2″, I also tried to enter and , but this messes up the layout. from the page. Last but not least the navigation is displayed at the top until I am scrolling down and than it disappears behind the following pages. I have tried to correct this with the z-index but that doesn’t change anything.

    Maybe some stupid questions but I can’t find the solution. I am trying to learn some html, css, jQuery for some month now and maybe it’s my age but I can’t figure out what I am doing wrong.

    The site is hosted at

    It would be great if someone could help me out.

    Thanx in advance


    • Claudia Romano

      Hi Peter, glad you liked it! The .cd-secondary-nav should not be inside the .cd-bg-1 element (this is way it’s not visible when you start scrolling). In addition, you should assign an id=”cd-placeholder-1″ to one of your .cd-scrolling-bg or .cd-fixed-bg to make it work. Hope this helps!

  • 21cdb

    Would it possible to scroll automatically to the first content section once the user scrolls/swipe down (and while doing so apply the transformation of the navigation) but afterwards return to regular scroll-behaviour until the page reached the very top again.

    Background: I appreaciate an animated and automatic on-scroll page-reveal effect (visually similar to but find it odd if user scrolls up and once he reach section one again the effect cause exactly it’s opposite intention as it is automatically covering the content. Normal scroll behaviour until you reach the top of the page again would feel more natural while providing the benefit of an animated and automatic on-scroll page-reveal effect once users reach the very top again.

    Could you give any instruction how to achive the described behaviour?

  • Stéphane

    Great stuff!
    Why the jquery file is over 250K?

    Is it possible to have it smaller (like multiple files)?
    Thank you

    • Sebastiano Guerriero

      you can compress it, there are several tools to get a minified version of your jQuery

      • Stéphane

        Thank you sir. It work well!
        Now the file is only 83k.

  • Jesse David Kevon

    Hi, any tips on how to allow for multiple instances of a dropdown?

    For example

  • Christian Conrad

    Hello Claudia! First of all, thank you for sharing. I find this build beautiful and very clean. Nice job! Would you mind if i use it as a base for creating an artists website? I would work on top of it, alter it and ad some cool things. I don’t want to use your idea without asking. Thanks in advance.

  • dave harrison

    Quick question. How do I make this unordered list of dots horizontal? Simply add a ‘display: inline’ somewhere to the CSS? Forgive me, I’m away from my laptop so I can’t play around with the code — I’m reading this from my tablet. Would changes to the jQuery be necessary? I love the simplicity but would like the same vertical scrolling with a horizontal navigation centered at the top of the page.

    Also, how does one get the page to open (start) at the bottom and scroll up instead of down?

    Any guidance appreciated! Thanks much!

  • Burhan

    Hi firstly thank you for such a great nav bar. I am currently developing a portfolio website and since I integrated the plugin for portfolio, it floats on top of my navigation bar but not the logo. So i changed the z-index for .secondary-nav ul and it solved my problem but now the logo fails to slide in when I scroll down. Any suggestion would be appreciated. Thanks in advance

  • Durra

    Why doesn’t links to external links work in the secondary navigation menu?

    • Claudia Romano

      Hi Durra, links inside the navigation are used to scroll to sections inside the same page. If you want them to link to external pages, you should remove, in the main.js file, the function to perform the smooth scroll.

      • Durra

        Thanks! That makes sense.

  • greatmj

    I have a fixed menu at the top. My menu has a lot of sub menu items which show from the main menu items when tapped on mobile devices. The problem is, when these lists overflow the page height, the menu items out of the view port cannot be accessed.

    Is there a workaround to let the user scroll through the fixed menu?

    • Claudia Romano

      Hi, you should try setting a max-heigh for you navigation and an overflow-y: scroll. Hope this helps.

      • greatmj

        Thanks! It just needed the max-height. Could you please explain why it wont work with overflow-y alone?

  • Sohaan Pensaalwar

    I replaced the icons inside the cd-nav-icons.svg file and I no longer see any icons now. Not sure why ? Any work around to change the icons ?

  • Javad Salari

    very useful :)

  • Adam Marsh

    Hi Claudia, loved the widget and works great. However, I can’t find where the breakpoints are defined. I see you commented your code, e.g. “//on mobile – open/close secondary navigation clicking/tapping the .cd-secondary-nav-trigger”. How are you defining “on mobile” if not with a media-query/breakpoints? I’m trying to change where the top nav icon appears (right now it appears at 767px). Thank you!

    • Claudia Romano

      Hi Adam, we use media-query inside the style.css (or partials/_layout.scss if you’re using sass). The .cd-secondary-nav-trigger is hidden if viewport width > 1170px (so you cannot tap it). Hope this helps!

  • Nenad Sladojević

    Hi Claudia. really great front. I’m .net developer and I need urgent site like this for my personal resume website. I read a license and I will customize theme and add maybe some features and host on server. I will credit you. Thank you.

  • Tyler

    Brilliant navigation!

    I was wondering if it is possible to incorporate the ‘secondary sliding nav’ found here –

    So when a user scrolls down, the secondary sliding nav is what gets fixed to the top, allowing the option of the slide in categories.

    Any advise on this would be GREATLY appreciated : )

    Again, brilliant work, I’m constantly blown away by the components I see you create!

    – Tyler

  • Xin Zao

    can i use it on my website please ?

  • Marianne

    I love this, i haven’t been able to find anything like it. I had to modify it to work on our site, but for some reason the links jump to the page sections instead of scrolling to them in Firefox only. i see you don’t have this issue in the demo. Would you happen to have any idea what I may be missing?

    Unfortunately I can’t share a link yet as it’s only running locally.

    • Claudia Romano

      Hi Marianne, you could have issues on Firefox if you don’t explicitly pass the event object to the callback function of the click event and then use it (e.g., event.preventDefault()). This may be a reason, not sure though!

      • Marianne

        I appreciate the reply Claudia, thanks so much! I will try and see if that helps.

  • Suriya

    Hi, I would like to use this Navigation with boostrap carousel, but this navigation has got fixed height. can anyone help me to use it without fixed height and should work properly with responsive bootstrap carousel. Thank you

  • Albert Lua

    The only thing I’m struggling to figure out is the navbar when it is in the mobile, condensed version: The menu is there, all right, but it seems when I open it, the items are all a little skewed, menu is off place, and there are the bullet points for the unordered list present. It doesn’t seem to be a CSS issue, I’ve removed all CSS except the bare minimum for the navbar and the issue still persists.

  • Yannick

    The one thing that would require a fix is the case in which the viewport size changes and the offset of the navigation becomes invalid. Simply wrapping the calculation of the offset in a function and using $(window).on(“resize”,…) solved this issue for me. I also changed the animation of the “left” property to use css transforms to prevent a repaint which can lead to slower frame-rates. But still, amazing ressources on this site and the consistent style is as always astonishing!