HTML5: Why a script tag needs to be placed at the end of body tag instead at the beginning of the body tag?

It's convention to have the dependencies (such as jQuery) within the head tag. However, without loading the DOM into the window there is no way for a script to access it.

Check out the following example:

<!DOCTYPE html>
<head>
   <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js
   </script>
</head>

<script type="text/javascript">
   $('#appleTest').html("Apples are great.");
</script>

<body>
   <div id="appleTest">
   </div>
</body>

If you were to run this, you would not see 'Apples are great.' in the browser window because the jQuery selection doesn't have anything to select. If you move the script to underneath the </body> tag, when the jQuery selector method is called, it can find the div since it has been loaded into the window.


javascript loading isn't part of the DOM, but it's blocking and it will interrupt the loading process until it's done. Even if it's a small script, it's still an extra request and will slow down the whole process.

Truth is browsers only need the DOM structure to start rendering, they don't need the scripts nor do they count for layout purposes. They are just dead weight until they are executed.

Even CSS could be considered unnecesary for the initial rendering process (more or less), but since CSS loading is non-blocking, this isn't an issue.

The performance gain from putting scripts at the bottom can vary, and even if it's a reccomended practice it might not always be harmless. When dealing with CMSs, for example, you might design your theme to load the scripts at the bottom, but you have no control over plugins. This happens a lot with wordpress, for example, and people end up putting script in the head to avoid conflicts with plugins.

Bonus Track (a few years later)

When in comes to tracking scripts, such as mixpanel, inspectlet, even google analytics... you might want to detect when a user enters your page and leaves a few seconds later due to slow loading times, an adult advertising block... whatever.

If you put the tracking script and the bottom it might not be able to boot in time to detect that visit, so you won't know you have such extreme bounce rate. In this case I'd consider putting the script in the head.

If you put resource hints at the beggining, say

<link rel="preconnect" href="https://api.mixpanel.com" />
<link rel="preconnect" href="https://cdn.mxpnl.com/" />

Or

<link rel="prefetch" href="https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" as="script">

It would mitigate the drawback of loading said scripts in the head.


It helps because the HTML page isn't rendered only after the DOM is ready: the browser starts rendering the page as it parses the DOM.

This means that you can achieve a faster "load" of the page (even though the DOM isn't ready) by making the browser load the scripts last. The user can see your page, and even interact with it, before those scripts at the end are loaded.

Of course, if your page is all built with scripts, there won't be much for the user to see.