172

Here is my brief HTML document.

Why is Chrome Console noting this error:

"Uncaught TypeError: Cannot call method 'appendChild' of null"?

<html>
<head>
    <title>Javascript Tests</title>

    <script type="text/javascript">

        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");

    </script>
</head>
<body>

</body>
</html>
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
John Hoffman
  • 17,857
  • 20
  • 58
  • 81
  • Does this answer your question? [Where should I put – Tomerikoo Feb 27 '23 at 10:19

7 Answers7

221

The body hasn't been defined at this point yet. In general, you want to create all elements before you execute javascript that uses these elements. In this case you have some javascript in the head section that uses body. Not cool.

You want to wrap this code in a window.onload handler or place it after the <body> tag (as mentioned by e-bacho 2.0).

<head>
    <title>Javascript Tests</title>

    <script type="text/javascript">
      window.onload = function() {
        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");
      }

    </script>
</head>

See demo.

Community
  • 1
  • 1
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • 1
    Thank you, what do you mean? Don't I have a body tag? – John Hoffman Mar 28 '12 at 22:45
  • 5
    The page is read from top to bottom and javascript executed along the way. You have some javascript in the `head` section that is being executed. But `body` part of the html, maybe, hasn't been even downloaded yet. Or it is downloaded, but it's still not evaluated at this point. So it doesn't exist in the DOM. – Sergio Tulentsev Mar 28 '12 at 22:47
  • 3
    What if you don't want to override an existing onload defined in another file? – The Student May 03 '13 at 22:05
  • 1
    @TomBrito: "or place it **after** the `` tag" – Sergio Tulentsev May 04 '13 at 03:52
  • 1
    Little bit late, but could also use addEventListener to attach the listener to the window, without replacing existing ones. – edvilme Jul 24 '19 at 00:27
59

Your script is being executed before the body element has even loaded.

There are a couple ways to workaround this.

  • Wrap your code in a DOM Load callback:

    Wrap your logic in an event listener for DOMContentLoaded.

    In doing so, the callback will be executed when the body element has loaded.

    document.addEventListener('DOMContentLoaded', function () {
        // ...
        // Place code here.
        // ...
    });
    

    Depending on your needs, you can alternatively attach a load event listener to the window object:

    window.addEventListener('load', function () {
        // ...
        // Place code here.
        // ...
    });
    

    For the difference between between the DOMContentLoaded and load events, see this question.

  • Move the position of your <script> element, and load JavaScript last:

    Right now, your <script> element is being loaded in the <head> element of your document. This means that it will be executed before the body has loaded. Google developers recommends moving the <script> tags to the end of your page so that all the HTML content is rendered before the JavaScript is processed.

    <!DOCTYPE html>
    <html>
    <head></head>
    <body>
      <p>Some paragraph</p>
      <!-- End of HTML content in the body tag -->
    
      <script>
        <!-- Place your script tags here. -->
      </script>
    </body>
    </html>
    
Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
8

Add your code to the onload event. The accepted answer shows this correctly, however that answer as well as all the others at the time of writing also suggest putting the script tag after the closing body tag, .

This is not valid html. However it will cause your code to work, because browsers are too kind ;)

See this answer for more info Is it wrong to place the <script> tag after the </body> tag?

Downvoted other answers for this reason.

Community
  • 1
  • 1
Martin Hansen
  • 5,154
  • 3
  • 32
  • 53
5

Or add this part

<script type="text/javascript">

    var mySpan = document.createElement("span");
    mySpan.innerHTML = "This is my span!";

    mySpan.style.color = "red";
    document.body.appendChild(mySpan);

    alert("Why does the span change after this alert? Not before?");

</script>

after the HTML, like:

    <html>
    <head>...</head>
    <body>...</body>
   <script type="text/javascript">
        var mySpan = document.createElement("span");
        mySpan.innerHTML = "This is my span!";

        mySpan.style.color = "red";
        document.body.appendChild(mySpan);

        alert("Why does the span change after this alert? Not before?");

    </script>

    </html>
Boris Bachovski
  • 642
  • 2
  • 12
  • 22
3

You need to put <script src="...">...</script> of your file at the end of the body tag:

<!DOCTYPE html>
<html lang="en">
        
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>you can see this</title>
        
       //-------------------------*** not here ***---------------------
        
    </head>
        
    <body>
        <div class="container">
            <div class="no">this is my dummy div1</div>
            <div class="no">this is my dummy div2</div>
            <div class="no">this is my dummy div2</div>
            <div class="no">this is my dummy div2</div>
        </div>
       
        //-------------------------*** here ***---------------------
        
        <script src="...js">...</script>
    </body>
</html>
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
1

Browser parses your html from top down, your script runs before body is loaded. To fix put script after body.

  <html>
  <head>
       <title> Javascript Tests </title> 
  </head>
 <body>
 </body>
  <script type="text/javascript">

    var mySpan = document.createElement("span");
    mySpan.innerHTML = "This is my span!";

    mySpan.style.color = "red";
    document.body.appendChild(mySpan);

    alert("Why does the span change after this alert? Not before?");

</script>
</html>
Emmanuel N
  • 7,350
  • 2
  • 26
  • 36
0

document.body is not yet available when your code runs.

What you can do instead:

var docBody=document.getElementsByTagName("body")[0];
docBody.appendChild(mySpan);
Christophe
  • 27,383
  • 28
  • 97
  • 140