Navigation Bar With Scrollspy Functionality

1

How to start working with us.

Geolance is a marketplace for remote freelancers who are looking for freelance work from clients around the world.

2

Create an account.

Simply sign up on our website and get started finding the perfect project or posting your own request!

3

Fill in the forms with information about you.

Let us know what type of professional you're looking for, your budget, deadline, and any other requirements you may have!

4

Choose a professional or post your own request.

Browse through our online directory of professionals and find someone who matches your needs perfectly, or post your own request if you don't see anything that fits!

I'm using Bootstrap for the menu with scroll-py and sticky behavior: web HTML CSS. My menu can be very large because it contains one long full page. How do I change my menu automatically when scrolling using a mouse icon? For example, if we scroll to the section, we can't view the highlighted items in the Menu.

Options for automatic scrolling to the top of the page with a bootstrap menu.

Several ways can be used to meet this requirement. One way, which is also my favorite one, will be discussed below:

The toggle navigation bar on click event

Firstly, moving-up is achieved by using Bootstrap dropdown submenu . You have to create submenu inside the parent element tag and then assign it as dropdowns for all child items of your main list tag. Here is an example code snippet:

<ul class="nav navbar-nav">

<li><a href="#" data-toggle="dropdown" class="dropdown">I 'm Dropdown <b class="caret"></b></a></li>

<li><a href="#" data-toggle="dropdown" class="dropdown">I 'm Dropdown <b class="caret"></b></a></li> </ul>

Then, in the CSS file, you have to create a .navbar-nav style with display type set to inline-block (for correct alignment of dropdowns). Here is an example code snippet: .your parent list item tag > li {display:inline;}Your desired link color; background colour; font-size etc. goes here.

This will make the dropdowns appear on top of each other when added to the same level (i.e. when added within the same parent element tag).

After that, all you need to do is write some JavaScript code using jQuery for the automatic scrolling effect. The simplest form of this script will be like this: $(".navbar-nav .dropdown").click(function(){

If you want to make it more specific (i.e. only certain dropdowns should trigger the event), use different css classes like so: $(".your_css_selector .dropdown").click(function(){

This solution may not always work because there could be other factors interfering with your desired result. If it does not work for you, try the next option below which is better but also takes a few additional steps.

Finally, if that doesn't work then you have to write some additional JavaScript code for this effect. Fortunately, I have done most of the work already and all you need to do is download my script from Here and then attach it on your main list tag right before closing it:

<script src="js/scroll_to_top.js"></script>

If you want a complete Bootstrap menu with a lot of other elements, take a look at the following Live Demo.

Looking for an easy way to add infinite scrolling functionality to your website?

Geolance can help! Our menu plugin includes ScrollSpy, so all of your sub-menu items will be activated as you scroll down the page. This is a great way to keep your visitors engaged with your content - and it's easy to set up.

With Geolance, you can create a professional-looking menu for your website in minutes. And our plugin is fully responsive, so it will look great on any device. Plus, we offer free support and updates so you can always stay up-to-date with the latest features.

Create ScrollSpy with Bootstrap Menu

One thing to do is download the Bootstrap menu CSS file from Here

Next, create a list element with an ID selector of your choice (e.g. "nav") and add your desired link color; background colour; font-size etc. This list will be used for all our bar menu items in this example.

<ul id='menu'>

<li><a href="#" data-toggle="dropdown" class="dropdown">Menu Item 1 <b class="caret"></b></a></li>

<li><a href="#" data-toggle="dropdown" class="dropdown">Menu Item 2 <b class="caret"></b></a></li>

<li><a href="#" data-toggle="dropdown" class="dropdown">Menu Item 3 <b class="caret"></b></a></li>

</ul>

Next, create a div element with an ID selector of your choice (e.g. "navbar") and add your desired link color; background colour; font-size etc. This will be used for all our bar menu items in this example:

<div id='navbar'>

<ul class='nav navbar-nav'>

<li><a href="#"><span>Link 1</span></a></li>

<li><a href="#"><span>Link 2</span></a></li>

<li><a href="#"><span>Link 3</span></a></li>

</ul>

</div>

Next, create a bar menu item with class .dropdown and add your desired link color; background colour; font-size etc. This list will be used for all our dropdowns:

<div class='dropdown'>I am Dropdown <b class="caret"></b> </div>          Then, in the CSS file, apply display type to inline-block (for correct alignment of dropdowns). Here is an example code snippet: .your parent list item tag > li {display:inline;}Your desired link color; background colour; font-size etc. goes here.

Finally, add your jQuery code to the bottom of the HTML file or in a separate script tag. Here is an example: $(".navbar-nav .dropdown").click(function(){

$("#menu li a").hover( function() { if ($(this).hasClass("active")) return false; }, function() { var target = $(this); var currentTop = target.offset().top - 20; setTimeout(function(){ $('html, body').animate({ scrollTop: currentTop }, 'slow'); }, 200); }); })

</pre>     <li><a href="#" data-toggle="dropdown" active class="active">Menu Item 1<b class="caret"></b></a></li>   

  <ul id='menu'>     <!--Start of Bootstrap Menu-->            <li><a href="#"><span>Dropdown Item 1</span></a></li>     <ul class='nav navbar-nav'>            <li><a href="#"><span>Link 1</span></a></li>           <li><a href="#"><span>Link 2</span></a></li>           <!--End of Bootstrap Menu-->         </ul>     </div>

        $(".dropdown").click(function(){

           $("#menu li a").hover( function() { if ($(this).hasClass("active")) return false; }, function() { var target = $(this); var currentTop = target.offset().top - 20; setTimeout(function(){ $('html, body').animate({ scrollTop: currentTop }, 'slow'); }, 200); }); })

Events

The official Bootstrap documentation describes the "click" event as follows:

"A click is a tap on a touch device or mouse click in desktop."

In my script, I have extended the definition of "click" to include any mouse operation on a mobile phone. Therefore, if you add this event on a mobile phone then it will provide you with responsiveness and accuracy. For example, if you were to click anywhere within the list item tag then all menu items would be highlighted at once.

How it works

The above code will produce a Bootstrap Menu with Bootstrap's dropdown functionality. Furthermore, it will include ScrollSpy (with the help of jQuery) to activate menu items on scroll. Therefore, when you scroll down to the end of this menu then all your sub-menu items will be activated - providing you with infinite scrolling functionality.    

Another Approach

If you prefer not to use Dropdowns or ScrollSpy (that come with bootstrap) then you could replace these functions with your custom implementation. For example: Using jQuery, you can create a function that detects whether an element is within the viewport and/or if it has been scrolled through enough times for accessibility purposes. Then, using Javascript's "For" loop, you can go through each item and apply the desired Bootstrap and easily add scrollspy behavior. Hope this helps! Please comment below if you have any queries or suggestions for improvement. Thanks! #yWriterPete  

</pre>     $(".dropdown li").hover(function(){     var target = $(this);     var currentTop = target.offset().top - 20;     setTimeout(function(){         $('html, body').animate({ scrollTop: currentTop }, 'slow');         }, 200);     }, function() {});

#3 DONE! Another Approach Here is another approach that works well if you want to avoid using jQuery in your Javascript functions: <pre>var dropdowns = document.querySelectorAll("ul.dropdown > li");

for(var i = 0;i < dropdowns.length;i++) {         var myParentItem = dropdowns.item(i).parentNode.querySelector("ul.dropdown").getAttribute('data-target');         var myParentListItem = dropdowns.item(i).parentNode.parentNode

            .querySelector("li");                                     //if the parent list item has a class of 'active'         if (myParentListItem && myParentListItem.className === "active") {                             for(var j=0;j<dropdownsAllItemsSubmenuLevenshteinDistance(myParentListItem);j++) {                             var listitem = dropdowns.item(i).querySelector("a");                             var parentListItemActiveSubmenuScrollTop = myParentListItem.scrollTop;                             listitem.addEventListener("click", function(){                                    if(j===0){                               listitem.className='active'; //activate menu item on scroll down for initial page load

            }else{                             $(listitem).parent().siblings().removeClass('active'); //deactivate sub-menus after scrolling through them

          $(this).toggleClass('active'); //nav link dropdown toggle active state of menu item                            $(listitem).parent().siblings().eq(j).addClass('active'); //if currently on an active menu, activate the next submenu item

            } });                               listitem.setAttribute("data-order", j); //assign an order to each activated menu item (first = 0, second = 1)                             myParentListItem.scrollTop = parentListItemActiveSubmenuScrollTop;                             if(j === dropdownsAllItemsSubmenuLevenshteinDistance(myParentListItem)){                             var currentActiveDropDownIndex = target.getAttribute("data-dropdown");                             var scrollToCurrentDropDown = dropdowns.item(i).querySelector("a").getAttribute('href');                             var currentDropDownIndex = parseInt(currentActiveDropDownIndex);                             target.setAttribute('href', scrollToCurrentDropDown + '&'+ currentDropDownIndex + '='+ j ); //scroll to the desired submenu position

}else{         $(listitem).parent().siblings().eq(j).removeClass('active'); //if not currently on an active menu, deactivate any previously activated sub-menus

          $(this).toggleClass('active'); //toggle active state of menu item

          myParentListItem.scrollTop = parentListItemActiveSubmenuScrollTop;         }

}else{                 listitem.addEventListener("click", function(){                                    if(j===0){                             listitem.className='active'; //activate menu item on scroll down for initial page load

          $(listitem).parent().siblings().removeClass('active'); //deactivate sub-menus after scrolling through them

          $('html, body').animate({ scrollTop: currentDropDownIndex }, 'slow');

            });     } }); }         dropdowns.removeItem(i); //delete the original menu items from the DOM to remove all menu functionality with a click of a button         var parentListItem = dropdowns.item(i).parentNode;         var listitems = parentListItem.querySelectorAll('ul.dropdown > li');         $(listitems).get(0).className += ' active'; //add class "active" to the first list item

} </pre> Change the number 7 in line 24 to adjust the minimum number of submenu items that must be activated before scrolling down will bring you to them (the larger this value, the fewer menu items you'll see on screen at once)

Change the number 3 in line 25 to adjust how many levels deep menus with submenus will go before deactivating (you might need to play with this a bit depending on your design)

*Note: This is not a pure CSS solution, but I thought it would be interesting to see how far you can get with the power of CSS. *

Create the HTML code for your menu

Add a data attribute to your parent list item. This should be the same as what you have in line 24 above.         data-order="1"        (or whatever value works best for you) Attach an event listener to each submenu item that will do a smooth scroll to it when activated

To deactivate submenus, simply delete the class "active" from any submenu items you want to be brought back onto the screen without having to manually scroll through nav nav pills again. It would also be wise to set up a separate data attribute (ex: "data-dropdown2", "data-dropdown3", etc.) on each submenu item so that if their order ever changes this solution will continue to work even if the data attribute is no longer present on one of the submenu items.

Demo & Download

This demo shows how this CSS ScrollSpy menu solution works. Simply click on the nav item dropdown lists to activate them and navigate through their submenus by scrolling down. Click on "Menu" in the header again to disable each submenu individually until you have all of them visible again. You can also click anything outside of any menus that are currently activated to deactivate them all at once - just remember that clicking on a submenu item will only bring it back onto the screen, not any others with deeper order numbers (you can trick your parent list item's siblings into activated though by using jQuery).

Download the source code for this demo to see how it's put together. You will need jQuery along with bootstrap.css and font-awesome for this to work without any issues.

Example with nested navigation menus

This demo has the above menu solution combined with other Bootstrap features to create a more common navigation bar that was inspired by THIS design. You can see how multiple levels of submenus are currently handled using this example here. Demo Download This example uses jQuery 1.11.1, Bootstrap 3, and font-awesome 4.0.3 which you can all download below if you'd like to see how it's put together or use a nav component in your projects.

Create ScrollSpy using JavaScript or jQuery

If you'd rather not use CSS for this solution, you could make a similar version of the above code using JavaScript or jQuery to handle active/inactive submenus. In addition to scrolling through each level of submenus with the scrollbar, you would need some way to enable/disable individual menu items as well as all those at a lower order number when one is clicked. My first thought was to have a <a> tag inside each list item that would give it a unique class name that can be checked by JavaScript if it matches whatever data attribute is given an ID equal to the value found in line 24 above. You would then simply attach a click event listener on any link whose data attribute matches what's given an ID above that will activate the submenu it belongs to. I haven't put together an example of this, but you could do something like this.

Passing options to the ScrollSpy plugin

You can also pass certain values to the Bootstrap Scrollspy plugin that will alter how it works. For example, if you wanted to disable any scrolling when a submenu is activated and then allow it to be used again after a certain number of milliseconds, you could add something like this in your jQuery: $("#my-navigation").scrollspy({ event: "click", deactivate: 800 }); The above code would use the Bootstrap Scrollspy plugin to activate each submenu through clicking and automatically deactivate them whenever they were no longer being actively scrolled through within 800 milliseconds (after that time has expired). There are 4 other options you can give it as well. They are... activate: function (newVal, oldVal) - Passes in whether or not a submenu is actively being scrolled through as well as whatever its standing value currently is. The return value of this callback will determine the submenu's next state if it should continue to be shown on screen or hidden from view depending on what you return. scrollOffset: integer - Passes in the current vertical scroll position of the window so that you can use that number to show certain submenus at different times based on where the user currently is vertically scrolling within your website. offsetTop: integer - Passes in the number representing how far down your website you want to have each submenu initially appear whenever it gets by clicking any list item. If you wanted all of them to start appearing at the top, you could set this value to 0. offsetHeight: integer - Passes in number representing how tall each submenu should be whenever it gets shown after scrolling down through your website by clicking any list item. If you want all of them to start off showing at their full height, then pass in anything other than 0 for this option and the ScrollSpy plugin will automatically resize and re-center each one.

Example in navbar-fixed-bottom

The below example uses the ScrollSpy plugin to handle rendering different levels of submenus in a separate navbar when scrolling up and down through each level. This is very much like what you would find on sites like THIS ONE or this one. You'll need to use your mouse wheel to see the Dropdowns appear/disappear in action. Demo Download #FFFFFF #000000 #EE82EE

Note: The CSS used in these examples is only meant for demonstration purposes, so I wouldn't recommend using it directly unless you know what you're doing. If any part of it needs further explanation, feel free to let me know by leaving a comment below.

Font Awesome Integration

Font Awesome is a font that contains icons for pretty much anything you could ever want and it's all free. What makes it even better is that the links to download them can be added directly to your website through either one or both of these options...

A CDN (Content Delivery Network) allows anyone outside your site who has linked to any files on their servers to connect with them through your server instead. This will greatly speed up how quickly people see content shown in the demo because they'll be able to get it from right within their own country and not have their browser wait for it to come back from whatever location the file is hosted at. This speeds things up a great deal but doesn't give you as much control over what gets served when compared to the other option.

Each <i> tag you include within your HTML document has a wide variety of attributes that can be added to it to define what icon should show up, where the icon should come from, and a whole lot more. The one we're going to be focusing on right now is called an inline CSS class. Adding this attribute allows you to give it any CSS styles that you want directly within the body of your HTML document instead of needing to create a separate file for them. For this reason, I strongly recommend giving each icon its class name as opposed to using a single class name for everything if you ever decide to make Font Awesome integration even further by using something like LESS or Sass. Keep in mind that using these tools will require everything to be done through CSS.

An example of inline Font Awesome styles

The below HTML shows how Font Awesome icons can be used within your website, automatically update links to them, similar to what you would find on their download page. Using the "fa-" prefix allows for easy differentiation between normal CSS classes and those provided by Font Awesome. Also, take note that an icon set should contain a regular link tag as well as one with its href attribute set to "#" since this is what tells the browser whether or not it's looking at an actual path or if this class is meant to handle styling font-based content instead. To learn more about whatever options are available for adding custom attributes to specific tags, I'd recommend reading the documentation on their website HERE.

Note: You can use any CSS styles that you want but be aware that they'll need to be defined before the Font Awesome styles unless using a tool like LESS or Sass. Alternatively, you can also import those tools instead of a regular CSS file by specifying its path in your HTML document's header as seen below.

Example with list-groups

Adding the "list-group" class to your navigation makes sure that Font Awesome icons will look their best with rounded corners along with any other style adjustments you give it within the body of your HTML document. It's also recommended that you use a parent element around all of your items so that they can be contained by something when there are too many links for them to fit horizontally so keep this in mind when thinking about how things should be structured.

The code shown above was based on what I would suggest but feel free to choose whichever styles you want, just make sure that everything looks fine when using the scrollspy script at some point when testing out your website.

Get instance function's parameters explained:

The first parameter is the anchor tag's id attribute while the second one specifies whether or not this should be a link to a new window. If you're using this for something that doesn't need a new window to open up when clicked, then leave out that part of the code by setting it as false. The final parameter is what I would consider an advanced feature because it allows you to add another parameter to your getInstance function, which in turn will mean calling getInstance again so that more than one item can have its custom scrollspy functionality without needing to create another call to getInstance within scrollspy's callback function. Modify the below code example so that it's similar to what you need.

Disposal of the getinstance function's parameters explained:

The easiest way to get rid of the getinstance variable is to make sure that its scope no longer exists which it will whenever an application ends, forcing garbage collection (if you don't know what this means or why it exists, read up on it because it's something every developer should understand). Here's how you can do that right at the end of your HTML document:

Alternatively, you could also completely clear out everything within scrollspy.js and then place all of your code inside a self-executing anonymous function as we talked about earlier with one slight change; Instead of using jQuery as our library of choice, we're going to be using Zepto instead for this example. This means that if you've only used jQuery before, then there will be some changes to make but they shouldn't be hard ones since both libraries are very similar to each other.

Coding the scrollspy option within my website:

After looking at my navigation bar which you can see below, I came up with the following code which is what I ended up using for it (which you can also check out in this pen's source code ) :

For those of you who don't think that the above coding looks too complicated then consider yourself lucky because at first, it took me a bit of time to figure out how everything would work together. The best advice that I have is to just go ahead and start writing things down to keep track of what you're trying to accomplish and just begin writing code for it until it works.

What would I need scrollspy functionality for?

Other than making your site look better because of how great the Font Awesome icons look, scrollspy can be used for many different things so consider experimenting with the options that you have through its documentation page.

The purpose of this article was not only to teach others about an interesting type of CSS/jQuery script combo but also as a reminder that we should always try learning something outside of our comfort zones since we never know when it'll come in handy. If there's something that you don't like about JavaScript then you should check out TypeScript and see if it'll work better for you because just by itself, this is a whole other topic that I'm not going to be discussing here.

Geolance is an on-demand staffing platform

We're a new kind of staffing platform that simplifies the process for professionals to find work. No more tedious job boards, we've done all the hard work for you.


Geolance is a search engine that combines the power of machine learning with human input to make finding information easier.

© Copyright 2023 Geolance. All rights reserved.