Anchor scrolling implemented with fixed navigation bar

I'm attempting to create a fixed navigation with anchor links that scroll smoothly to the designated section. The challenge lies in the fact that my navigation is positioned near the bottom of the screen. As a result, when the user scrolls down and the navigation receives a 'fixed' class, clicking on an anchor link causes the script to scroll too far to the anchor block. I've tried adjusting the offset of the nav by the height of the navigation itself, which somewhat solves the issue, but requires clicking twice on the same link for it to work properly.

To better illustrate the issue, I've prepared a Fiddle -> Fiddle

My assumption is that the scrollTo function and fixing the nav simultaneously might be causing conflicts. Does anyone have insights into what could be causing this problem?

The code structure is as follows:

<div class="anchor-links">
    <div class="anchor-wrapper">
        <ul class="nav-list">
            <li><a href="#description" class="goSmoothly">Product information</a></li>
            <li><a href="#bundles" class="goSmoothly">Product bundles</a></li>
            <li><a href="#reviews" class="goSmoothly">Reviews</a></li>
            <li><a href="#related" class="goSmoothly">Related products</a></li>
        </ul>
    </div>
</div>

<div id="description" class="block">description</div>
<div id="bundles" class="block">bundles</div>
<div id="reviews" class="block">reviews</div>
<div id="related" class="block">related</div>

var fixmeTop = $('.anchor-links').offset().top;

$(window).scroll(function() {
    var currentScroll = $(window).scrollTop();
    if (currentScroll >= fixmeTop){
        $('.anchor-links').addClass("sticky");
    } else {
        $('.anchor-links').removeClass("sticky");
    }
});

$('.goSmoothly').click(function(event){     
    event.preventDefault();
    $(this).addClass('active');
    $('html,body').animate({
        scrollTop: $(this.hash).offset().top - 100
    }, 500);
});

Answer №1

Give this a try.

var topPosition = $('.anchor-links').offset().top;

$(window).scroll(function() {
    var currentScroll = $(window).scrollTop();
    if (currentScroll >= topPosition){
        $('.anchor-links').addClass("sticky");
    } else {
        $('.anchor-links').removeClass("sticky");
    }
});

$('.goSmoothly').click(function(event){
    event.preventDefault();
    $(this).addClass('active');
    if( $('.anchor-links').hasClass("sticky")) {
    $('html,body').animate({
        scrollTop: $(this.hash).offset().top - 100
    }, 500);
    } else {
    $('html,body').animate({
        scrollTop: $(this.hash).offset().top - 220
    }, 500);    
    }
});
.block{
    height:700px;
    background:#eee;
}
.anchor-links {
  border-bottom: 1px solid #f5f5f5;
  border-top: 1px solid #f5f5f5;
  margin-bottom: 20px;
}
.anchor-links .nav-list li {
  display: inline-block;
  line-height: 4.2rem;
}
.anchor-links.sticky {
  background: #fff none repeat scroll 0 0;
  border-bottom: 1px solid #f5f5f5;
  left: 0;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img width="400" height="400" alt="Adidas 2 Options" itemprop="image" class="featured" data-original-url="http://static.webshopapp.com/shops/057743/files/029936946/adidas-2-options.jpg" src="http://static.webshopapp.com/shops/057743/files/029936946/400x400x2/adidas-2-options.jpg">
<div class="anchor-links">
    <div class="anchor-wrapper">
        <ul class="nav-list">
            <li><a href="#description" class="goSmoothly">Product information</a></li>
            <li><a href="#bundles" class="goSmoothly">Product bundles</a></li>
            <li><a href="#reviews" class="goSmoothly">Reviews</a></li>
            <li><a href="#related" class="goSmoothly">Related products</a></li>
        </ul>
    </div>
</div>

<div id="description" class="block">description</div>
<div id="bundles" class="block">bundles</div>
<div id="reviews" class="block">reviews</div>
<div id="related" class="block">related</div>

Now, instead of using a static value like -220 in the else block, you can calculate it dynamically based on the size of the header before and after being fixed.

As mentioned in the comment, removing the header from the body and fixing it can affect the scroll top of each section.

One solution is to add a placeholder when the header is fixed to avoid any calculation errors.

Answer №2

This code snippet is functioning well: JSfiddle.

HTML:

<div class="anchor-links">
    <div class="anchor-wrapper">
        <ul class="nav-list">
            <li><a href="#description" class="goSmoothly">Product information</a></li>
            <li><a href="#bundles" class="goSmoothly">Product bundles</a></li>
            <li><a href="#reviews" class="goSmoothly">Reviews</a></li>
            <li><a href="#related" class="goSmoothly">Related products</a></li>
        </ul>
    </div>
</div>
<div class="container">
<div id="description" class="block">description</div>
<div id="bundles" class="block">bundles</div>
<div id="reviews" class="block">reviews</div>
<div id="related" class="block">related</div>
</div>

CSS:

.container {
    margin-top: 100px;
}
.block{
    height:700px;
    background:#eee;
}
.anchor-links {
  border-bottom: 1px solid #f5f5f5;
  border-top: 1px solid #f5f5f5;
  margin-bottom: 20px;
  position: fixed;
  top:0;
  left: 0;
  background: #fff;
  width: 100%;
}
.anchor-links .nav-list li {
  display: inline-block;
  line-height: 4.2rem;
}
.anchor-links.sticky {
  background: #fff none repeat scroll 0 0;
  border-bottom: 1px solid #f5f5f5;
  left: 0;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 99;
}

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

javascript/jquery - steps to design an effective modal page overlay

Struggling for the past few weeks to create a modal dialog using javascript/jQuery. While iOS and Android devices seem to work fine, Windows mobile/Opera mobile often present issues with the modal size. It either requires excessive scrolling or ends up bei ...

Leverage information retrieved from an AJAX request

I have a situation where I am using a self-hosted API and trying to use the data retrieved from an AJAX call in another function, but it seems to be not working as expected. The issue I am facing is that I am getting 'undefined.' Here's my ...

Is the this.props.onChange method called within the render function?

I'm having trouble grasping the concept of the assigned onChange property in this TextField component I found in the material-ui library: <TextField style = {{"padding":"10px","width":"100%"}} type = {'number'} valu ...

Is there a way to arrange the outcomes in a single line?

I need help displaying my results in three rows side by side in React/JavaScript using flexbox. Since I only have one CardItem, I can't just copy and paste it three times as it would show the same result in each row. Is there a way to achieve this wit ...

Error: Query has already been processed: Updating Todo with ID "612df063a8f"

After updating mongoose to the latest version (6.0.2), I encountered an error that crashes the application whenever .updateOne() is executed. However, the object is still updated inside the database. Below is my code snippet: async(req,res) => { a ...

JavaScript Popup prompting user on page load with option to redirect to another page upon clicking

Can a JavaScript prompt box be created that redirects to a site when the user selects "yes" or "ok," but does nothing if "no" is selected? Also, can this prompt appear on page load? Thank you! UPDATE: Answer provided below. It turns out it's simpler ...

Ensuring data validity in Angular 2 before enabling a checkbox

In my form, there is a checkbox for admins to edit user accounts. Each user object includes a boolean value isAdmin. I am trying to prevent users from editing their own account while still allowing them to view the values. However, no matter what I try, I ...

Is it possible for Javascript to manipulate the DOM of an Ajax text/html response?

My goal is to implement Ajax to retrieve an HTML page and extract a specific div by its ID, then insert that div into the current page. This involves loading a second page via Ajax, extracting the specified div from the response, and placing it within th ...

Load the values into the dropdown list based on the selection from the previous dropdown menu

Currently, I am working on implementing cloning functionality for select boxes. There are 3 select boxes: country, state, city. The user selects the country first which then populates the state select box based on the ID, and similarly, the city dropdown ...

Looking to incorporate an Ajax feature that allows for updating dropdown menus in each row of the database

Please find below the UI screenshot highlighting the dropdown menu: What I am looking for? I would like the option selected in the dropdown menu to be updated for each specific row in the database using AJAX. Below are the codes I have written. As a beg ...

Generating an Array of objects through the use of the each method

Currently, I am in the process of developing a web scraper using node.js along with puppeteer and cheerio. Although I can successfully display the desired strings in the console.log, I am facing challenges in determining if this task is achievable. $(&apo ...

Angular binding for selecting all data

Upon checking a checkbox for a single item, the bound data is retrieved and added to an array. However, this does not happen when using selectAll. Code snippet in Angular for obtaining the object of a checked item: $scope.selectedOrganisations = []; $sco ...

Most effective method for eliminating an item from an array with AngularJs

I have an array of objects that I want to modify by removing multiple objects from it. The following code is currently achieving this successfully, but I'm curious to know if there is a more efficient way to accomplish this task. This process involv ...

Searching for data in Express JS with MongoDB using the $or operator is not possible

I am currently developing an API for managing my invoice data. Within this data, there are boolean values that determine the status of the invoices. For example, some invoices are marked as 'payment received', and I need to search for those speci ...

What is the rationale behind using :: before display: inline-block in Angular Material MDC's mat-mdc-form-field-error-wrapper, causing substantial padding?

I recently made the switch from Angular Material to Angular Material MDC in preparation for upgrading to Angular 17 from version 15. However, I've noticed that some styles are now broken. One issue I'm facing is a significant padding between the ...

The required validator in Mongoose is not being triggered by the function

I'm trying to use a function as a validator in a mongoose schema, but it doesn't seem to work if I leave the field empty. The documentation states: Validators are not run on undefined values. The only exception is the required validator. You ...

Tips for maintaining the integrity of blank space within a text node?

When intercepting a paste event and cleaning HTML off of the content using textNodes, I am faced with an issue where all white space is reduced to a single space and new lines are disregarded. For example, pasting: "hello world !" ends up being "h ...

Guide on how to vertically and horizontally center a heading text with dash-bootstrap

I have implemented the Bootstrap dash layout for my web application, but I want to place the text in the red area instead of at the top of the page. Can anyone guide me on how to achieve this? https://i.sstatic.net/RcNhy.png I have already tried using "a ...

Error: the given elements cannot be iterated over

I am currently working with Rect/Redux and I need to convert an array into a tree structure of children as described in this helpful guide: Transform an array of connected elements to a tree. The issue arises when I try to access the state and check the co ...

Infinite redirection occurs after loading with Jquery if Scriptaculous is installed

Whenever I use jQuery load to load a page that contains scriptaculous, the page keeps redirecting me back to itself after the initial load. Below is the jQuery code I am using to load pages: jQuery( document ).ready(function( $ ) { // Code that uses jQue ...