Issue with the back-to-top button arises when smooth-scrolling feature is activated

This Back To Top Button code that I discovered online is quite effective on my website.

// Defining a variable for the button element.
const scrollToTopButton = document.getElementById('js-top');

// Creating a function to display our scroll-to-top button when scrolling beyond the initial window height.
const scrollFunc = () => {
  // Getting the current scroll value
  let y = window.scrollY;

  // Adding a class to the scroll-to-top button based on scroll location
  if (y > 100) {
    scrollToTopButton.className = "top-link show";
  } else {
    scrollToTopButton.className = "top-link hide";
  }
};

window.addEventListener("scroll", scrollFunc);

const scrollToTop = () => {
  // Setting up a variable for the distance from top of document.
  const c = document.documentElement.scrollTop || document.body.scrollTop;

  // Scrolling back to top with animation using requestAnimationFrame
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    // ScrollTo takes x and y coordinates. Adjust speed by changing '10' value.
    window.scrollTo(0, c - c / 10);
  }
};

// Running ScrolltoTop function on button click
scrollToTopButton.onclick = function(e) {
  e.preventDefault();
  scrollToTop();
}

However, whenever I try to add smooth scrolling for better user experience:

html {
   scroll-behavior: smooth;
}

The back-to-top button starts glitching.

I wish to have the back-to-top button also smoothly scroll along with the rest of the content on the page, including anchor links in the navigation linking to sections on the same page.

Answer №1

If you want a smooth back-to-top experience, this code will help you achieve that.

// Define the variable for the button element.
const scrollToTopButton = document.getElementById('js-top');
smoothScrollCapture = (x) => {
  event.preventDefault();
  var id = event.target.getAttribute('href').split("#")[1]
  var el = document.getElementById(id);
  var x = el.getBoundingClientRect().left
  var y = el.getBoundingClientRect().top
  smoothScrollFunc(x, y)
}

smoothScrollFunc = (x, y) => {
  event.preventDefault()
  window.scrollTo({
    top: y,
    left: x,
    behavior: 'smooth'
  });
}

window.addEventListener('DOMContentLoaded', () => {
  scrollToTopButton.addEventListener('click', () => {
    smoothScrollFunc(0, 0)
  })

  var aTags = document.getElementsByTagName('A')
  var myTags = []
  for (var i = 0; i < aTags.length; i++) {
    if (aTags[i].getAttribute("href").indexOf('#') === 0) {
      aTags[i].addEventListener('click', smoothScrollCapture);
    }
  }
})

window.addEventListener('scroll', () => {
  // Get the current scroll value
  let y = window.scrollY;
  if (y > 100) {
    scrollToTopButton.style.display = 'block'
  } else {
    scrollToTopButton.style.display = 'none'
  }
})
#js-top {
  position: fixed;
  /*OR WHATEVER YOU PREFER*/
  bottom: 10px;
  /*OR WHEREVER YOU PREFER*/
  left: 50%;
  /*OR WHEREVER YOU PREFER*/
  display: none;
}
<div style="height: 1000px;">
  <div class="nav-items">
    <a href="#paragraph1">Paragraph One</a>
    <a href="#paragraph2">Paragraph Two</a>
    <a href="#paragraph3">Paragraph Three</a>
    <a href="#paragraph4">Paragraph Four</a>
  </div>

  <div style="height: 100px;"></div>
  <p id="paragraph1">Here is the first paragraph!</p>
  <div style="height: 100px;"></div>
  <p id="paragraph2">Here is the second paragraph!</p>
  <div style="height: 100px;"></div>
  <p id="paragraph3">Here is the third paragraph!</p>
  <div style="height: 100px;"></div>
  <p id="paragraph4">Here is the fourth paragraph!</p>
</div>

<button id='js-top'>Scroll To Top</button>

EDIT I have made some changes to the code snippet. While there may be a CSS-only solution, I have used JavaScript to enhance the smooth scroll functionality for navigation links on your page. The JavaScript code captures anchor tags with href attributes referencing specific IDs and applies the smooth scrolling effect through functions like smoothScrollCapture and smoothScrollFunc.

This approach saves you from modifying your HTML by individually assigning classes to every navigation item on your page.

In the smoothScrollCapture function, when you click a navigation link (e.g. paragraph3), the script extracts the ID from the href attribute of the clicked element and retrieves the top and left positions using getBoundingClientRect(). These values are then passed to the smoothScrollFunc which smoothly scrolls the page to the specified coordinates.

All initialization tasks are wrapped in a DOMContentLoaded event listener for proper execution. This includes attaching smoothScrollCapture to anchor tags, setting up the click event for scrollToTopButton, and specifying the coordinates as 0 while navigating to the top of the page.

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

Using PHP to globally access a JavaScript object named

I have a collection of CSS attributes stored in a MySQL database that are accessed using PHP. These attributes need to be accessible to JavaScript once the page has finished loading. To achieve this, I loop through each row and create a JavaScript object ...

Obtain the user's email using nodemailer

I created a contact form using Nodemailer that I am having trouble with. Take a look at the code below: let mailOptions = { from: '<<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e3636360e363636602d2123">[emai ...

Tips for obtaining a specific sorting order based on a wildcard property name

Here's the structure of my JSON object, and I need to sort it based on properties starting with sort_ { "sort_11832": "1", "productsId": [ "11832", "160", "180" ], "sort_160": "0", "sort_180": " ...

Is there a way to prevent an item from being selected in a Select component when the first letter of the option is pressed?

I'm currently working with the material UI Select component and I'm attempting to create a filter within it that will only display items matching the user's input. Below is a simplified example of my current project: function App() { con ...

Is the .html page cached and accessible offline if not included in the service-worker.js file?

During the development of my PWA, I encountered an unexpected behavior with caching. I included a test .html page for testing purposes that was not supposed to be cached in the sw.js folder. Additionally, I added some external links for testing. However, w ...

Interactive JavaScript Linkage

Recently, I came across some code that I inherited (definitely not mine!) which uses a session variable in the HTML header to link to a specific javascript file. For example: <SCRIPT language="javascript" src="../JavaScript/<%=Session("jsFileName") ...

Is it possible to activate the identical drop-down or popover with multiple buttons?

Is it possible to activate the same drop-down menu with multiple buttons? For example, I want a button at the top of the page labeled special menu, another in the middle also labeled special menu, and one at the bottom as well labeled special menu. When a ...

The back button fails to refresh the page on a website utilizing Ajax technology

Recently, I implemented AJAX on a client's website to introduce some smooth animations for page transitions. When navigating from the homepage of firedogcreative.com to the edit page, and then to one of the work pages, we see a history like this: fir ...

Simultaneously, two identical messages arrived in the form of push notifications via FCM

I have been working on implementing WebPush notifications using Vue.js and FCM. However, when testing the functionality, I am facing an issue where instead of receiving just one notification from Firebase, TWO IDENTICAL PUSH NOTIFICATIONS are being receive ...

Using jQuery in Yii: Detecting when a radio button loses its checked state

Here is the code regarding the issue at hand: <script> $(function(){ $('#widgetId-form input[name="valueType"]').change(function(){ if ($(this).is(":checked")) { console.log("enabling "+$(this).data("class") ...

Unable to process form submission with AngularJS + Stormpath

I am facing an issue with form submission. Even though I believe that the login and password data are being sent correctly, nothing happens when I submit the form. I am attempting to submit the form without using ngSubmit because it is not feasible in my s ...

How to smoothly transition a div from one location to another using animations in an Ionic3-Angular4 application

I'm attempting to incorporate some animation into my Ionic 3 mobile app. Specifically, I want to shift a div from one location to another. In the code snippet provided below, I am looking to move the div with the "upper" class after the timeline-item ...

Using a combination of radio buttons and JavaScript to adjust the color of a div element

Currently, I am experimenting with radio buttons to modify the background color of my div tag. My goal is to incorporate more than one condition. For example, if button A and button B are both clicked, then change the color to green. This is what I have im ...

JavaScript issue with confirm/redirect feature not functioning as expected

A demonstration of JavaScript is utilized for deleting an employee in this scenario... <script type="text/javascript"> function deleteEmployee(employee) { var confirmation = confirm('Are you sure?'); if(confirmation) { ...

Seeking guidance on resolving issues with this div table

After almost getting everything set up, I encountered some strange issues that have been difficult to resolve. The challenges I'm facing include: The spacing on the right side is too large. Tables always appear stacked without any spacing in bet ...

Retrieve the data from an input field in Selenium automation

Despite the text being visible in the input Text Box, I am encountering difficulties capturing it from the html DOM. I attempted to use getAttribute('value'), however, since the value attribute is not present, this method proved unsuccessful. Sim ...

Is there a way to retrieve the filename from a callback in gulp-contains?

Currently, I am utilizing gulp-contains to scan for a specific string. If the target string is found, I intend to trigger an error message stating "String found in file abc." The 'file' parameter holds the entire object comprising filename + Buff ...

Using an if statement to run a script in Npm

Is there a way to configure an npm run script to use different AWS accounts based on the environment? { "config": { "acc": if ({npm_config_env} == "dev") "account1" else "account_2" }, "scr ...

What is the best way to attach an image to the image section coming from the backend in vue.js?

I have developed a frontend page that displays a list of books, with the data coming from the backend. The backend response includes image files, and I am struggling to bind these images to the image section of my template. I have the image paths from the ...

Send data from input to controller without using $scope

I am encountering an issue with the code below. Typically, I would resolve this problem using $scope, but this time I have been asked to find a solution without utilizing $scope in the controller. I am implementing the "controller as" syntax for managing ...