ERROR "document is not defined"

I wanted to create a ‘back to top’ button that only revealed itself once the page scrolled past a certain amount of pixels.
Below is the code:


//Get the button
let myButton = document.getElementById("myBtn");

// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};

function scrollFunction() {
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
    myButton.style.display = "block";
  } else {
    myButton.style.display = "hidden";
  }
}

// When the user clicks on the button, scroll to the top of the document
function topFunction() {
  document.body.scrollTop = 0; // For Safari
  document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
}

When I run this, the back to top function is working properly. However, the “hiding function” cant run because its says “the document is not defined” and therefore cannot define my variable (myButton)
I don’t understand because it seems to know what document means for the top function
I get the document not defined message when I used quokka.js to check what wasn’t working.
I get the following (every time I scroll) when I used chrome dev tools to inspect what’s going on:
Uncaught TypeError: Cannot read property ‘style’ of null
at scrollFunction
at window.onscroll

P.S this code and its css was copy/pasted from How To Create a Scroll Back To Top Button
The only modification I made was adding a ‘let’ to the myButton variable and camelcasing it.

If someone could help me with this, I’d greatly appreciate it. I’ve looked everywhere and cant find any solutions.

Hi @kev808
your function works when I run it, maybe it has something to do with how you load your Javascript. How did you embed/linked it?

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

I used this and put it in the head of my html

Then your Javascript loads before the DOM content, that’s why you get undefined. You could try to add the attribute ‘defer’ to the script tag:

<script src="./index.js" defer></script>

Then the DOM content and the Javascript load at the same time but the execution of Javascript is held back until the DOM content is loaded.

Ok, that worked but it has created some side-effects in my other bootstrap and js files :sweat_smile: :sob:.
It hasn’t created any problems visually or functionally. just some type errors when i inspect with dev tools.
Anyways thank you very much! :pray:t4:

You’re welcome.
Alternatively you could remove the defer attribute again and add the code you posted to an event listener instead:

document.addEventListener("DOMContentLoaded", function() {
  // code...
});