Styling anchors that are focused or visited while scrolling using CSS and jQuery

I'm facing a challenging question that I can't seem to figure out on my own.

At the top of my page, I have some anchors that smoothly scroll down to different articles:

I would like to indicate to visitors their location on the page by rotating an arrow. This arrow should point towards the article it represents. In the image below, you can see the desired implementation where as the user scrolls past anchor 1 (an article with dynamic height) and moves on to read anchor 2:

If the visitor is not within the article but the next anchor 3 article is still visible below the scrolled position, it should display as shown below:

However, this poses a couple of challenges for me:

  1. Is there a way to write a jQuery script that allows dynamically adding anchors?
  2. How can I incorporate a rotation animation without using an additional library? (Currently utilizing jquery.transit)

Current code snippet: (obtained from another post: jsfiddle.net/m2zQE)

 var topRange      = 200,  // measure from the top of the viewport to X pixels down
     edgeMargin    = 20,   // margin above the top or margin from the end of the page
     animationTime = 1200, // time in milliseconds
     contentTop = [];

$(document).ready(function(){ 

 // Stop animated scroll if the user does something
 $('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function(e){
 if ( e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel' ){
  $('html,body').stop();
 }
})

 // Set up content an array of locations
 $('#navTopBar').find('a').each(function(){
  contentTop.push( $( $(this).attr('href') ).offset().top );
 })

 // Animate menu scroll to content
  $('#navTopBar').find('a').click(function(){
   var sel = this,
       newTop = Math.min( contentTop[ $('#navTopBar a').index( $(this) ) ], $(document).height() - $(window).height() ); // get content top or top position if at the document bottom
   $('html,body').stop().animate({ 'scrollTop' : newTop }, animationTime, function(){
    window.location.hash = $(sel).attr('href');
   });
   return false;
 })

 // rotate arrow
 $(window).scroll(function(){
  var winTop = $(window).scrollTop(),
      bodyHt = $(document).height(),
      vpHt = $(window).height() + edgeMargin;  // viewport height + margin
  $.each( contentTop, function(i,loc){
   if ( ( loc > winTop - edgeMargin && ( loc < winTop + topRange || ( winTop + vpHt ) >= bodyHt ) ) ){
    $('#navTopBar .anchor img')
     .removeClass('open')
     .eq(i).addClass('open');
   }
  })
 })

})

Thank you in advance for your help!

Answer №1

That code seems familiar, doesn't it? ;)

Why not give this a try? (demo)

CSS

li.selected a:after { content :' \2192' }
li.above a:after { content :' \2191' }
li.below a:after { content :' \2193' }

Script

 var topRange = 200, // measure from the top of the viewport to X pixels down
     edgeMargin = 20, // margin above the top or margin from the end of the page
     animationTime = 1200, // time in milliseconds
     contentTop = [];

 $(document).ready(function () {
     var $menu = $('#sidemenu li'),
         updateArrows = function (sel) {
             var indx = $menu.filter('.selected').index();
             $menu
                 .filter(':lt(' + indx + ')').removeClass('below').addClass('above').end()
                 .filter(':gt(' + indx + ')').removeClass('above').addClass('below');
         };

     // Stop animated scroll if the user does something
     $('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function (e) {
         if (e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel') {
             $('html,body').stop();
         }
     });

     // Set up content an array of locations
     $menu.find('a').each(function () {
         contentTop.push($($(this).attr('href')).offset().top);
     });

     // Animate menu scroll to content
     $menu.find('a').click(function () {
         var sel = this,
             newTop = Math.min(contentTop[$('#sidemenu a').index($(this))], $(document).height() - $(window).height()); // get content top or top position if at the document bottom
         $('html,body').stop().animate({
             'scrollTop': newTop
         }, animationTime, function () {
             window.location.hash = $(sel).attr('href');
             updateArrows();
         });
         return false;
     });

     // adjust side menu
     $(window).scroll(function () {
         var sel,
         winTop = $(window).scrollTop(),
             bodyHt = $(document).height(),
             vpHt = $(window).height() + edgeMargin; // viewport height + margin
         $.each(contentTop, function (i, loc) {
             if ((loc > winTop - edgeMargin && (loc < winTop + topRange || (winTop + vpHt) >= bodyHt))) {
                 $menu.removeClass('selected')
                     .eq(i).removeClass('above below').addClass('selected');
             } else {
                 updateArrows();
             }
         });
     });

     updateArrows();

 });

If you're interested, I actually transformed that code into a plugin called visualNav; it may not have these specific changes like adding classes to links above and below the selected one, but it shouldn't be too difficult to incorporate them with the callback functions.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transmitting data via POST method within datatables ajax call

I am facing an issue while attempting to execute a simple ajax call in datatables that relies on a post array of IDs from a form on a previous page. The error I encounter is: Invalid JSON Response This indicates that the JSON array being returned may be ...

Tips on bringing data from a php file into a javascript variable

I'm faced with a challenge where I need to extract data from a MySQL database using a PHP file and then store that data in a JavaScript array for plotting purposes with jQuery's flot library. Has anyone encountered a similar situation and found a ...

The Page Transcends the Boundaries of the HTML Tag

This particular issue sets itself apart from the common overflow problems that are often faced by people. Interestingly, I have only encountered this problem while using Chrome (Version 41.0.2272.101 64-bit). IE 9+ and Firefox, on the other hand, seem to b ...

Hover over the Div element for inline effect

Hello all, I am currently working on running a while loop from a database to show different records. The twist is that these records are displayed as images, which makes it tricky to customize using standard CSS. To work around this, I'm implementing ...

Shadowy figure in block form

result photo and required modifications The image on the left shows the result I obtained in a browser, while the one on the right displays the desired outcome in Figma. I am struggling with creating a semicircle with a shadow under the coin and implemen ...

Do not refresh the ajax content

I'm using Ajax to dynamically load HTML content into a div container. The content is loaded when an element with the class "link" is clicked, as shown below: $(".link").click(function () { $('.link').removeClass('current'); ...

Styling elements with CSS

I've been attempting to align a button to the right of another button. The example above illustrates what I'm trying to achieve. I used Bootstrap to build it, which has a useful navbar feature for layout. However, despite my efforts to use right ...

Methods for scaling the size of CSS background images

Can anyone assist me with scaling background image size properly? code: http://codepen.io/AnilSimon123/pen/JRBRZa Below is the code snippet: .bgimage{ background:url('http://www.thedesignlove.com/wp-content/uploads/2012/08/free-blue-abstract-vec ...

Troubleshooting compatibility issues between jQuery scrollLeft and Angular

As I attempt to programmatically scroll a horizontally overflowing div, I am confident that my final code should resemble the following: var $element = $('#widgetRow');//or maybe $('#widgetRow').parent(); //With 1 or more parent()& ...

Customize the Kendo UI by integrating it with HTML tables and dropdown lists

I am trying to utilize an HTML table as the data source for kendo-ui jQuery, and also enable inline editing with a drop-down list. To achieve this, I have written the code below: However, my issue arises when a user double clicks on a row of the table to ...

Ajax facilitates the loading of multiple containers

My goal is to utilize Ajax to load dynamic content. The process starts with a list of countries. When a country is selected, the cities in that country are displayed, followed by suburbs, companies, branches, and eventually branch details: Countries --> ...

Adjust the transparency of an image preview using jQuery

Currently, I am working on creating a video gallery for a friend and I am experimenting with changing the thumbnail opacity using jQuery fade effect. While I can achieve this with CSS, I want to implement it with jQuery for a smoother transition. If you ...

Pause after applying the "scroll" animation to an element located close to the bottom of the webpage

On my webpage, I have implemented a feature where a downward pointing arrow inside a circle, located just above the fold, indicates there is more content below. When this arrow is clicked, jQuery triggers an animated scroll to the bottom of the page and th ...

Tips for extracting Ajax responses that are delayed

I am attempting to retrieve the response code for an email form that I sent to a PHP mailer page using ajax. If the email is successfully sent, it will echo 1; otherwise, it will echo 0. Below is the code snippet of how I submit the form: $('form.aj ...

Seamlessly log into AJAX without the need to refresh the page

When I tried logging into my iCloud account, I was amazed at how they were able to log me in without the page reloading. I know that it's not possible for jQuery to run PHP scripts or create a session after the page has loaded. I suspect they may be u ...

Customizing the appearance of input range in Firefox

I am having trouble styling the HTML input range element. I have successfully styled it for webkit browsers, but my styling does not seem to work on -moz- browsers. I attempted to use pseudo elements before and after on moz-range-thumb, but it seems that F ...

Floating and scrolling navigation bar not functioning properly in bootstrap framework

I've been dabbling in coding for a while now, practicing at my current job. I managed to create a floating and scrolling navigation bar on the right side of my website using bootstrap. However, after taking a 3-week break and returning to my site, I n ...

Basic draggable pop-up window using HTML5 for a seamless experience

Can anyone provide me with helpful resources or tutorials to create a draggable popup using HTML5 without jQuery? I want to keep it simple and avoid external libraries like jQuery UI. Currently, I have an absolutely positioned div that looks like a popup ...

Using Jquery, take out each parent element and duplicate the child element

It seems to be partially working, but I encounter multiple instances of the cloned element. My goal is to rearrange elements in my JavaScript when the browser viewport reaches a mobile size. Original Order: <div class="sar--img-right-first"> ...

Partial height side navigation bar

Check out this JS Fiddle: https://jsfiddle.net/wqbn6pe6/2/ This is a simple side navigation, but the grid layout is causing the sidebar not to stretch to the bottom even though it's set at 100% height. Any suggestions or solutions? Here's the ...