Is It Wrong to Place the ≪Script≫ Tag After the ≪/Body≫ Tag

Is it wrong to place the script tag after the /body tag?

It won't validate outside of the <body> or <head> tags. It also won't make much difference — unless you're doing DOM manipulations that could break IE before the body element is fully loaded — to putting it just before the closing </body>.

<html>
....
<body>
....
<script type="text/javascript" src="theJs.js"></script>
</body>
</html>

Where should I put script tags in HTML markup?

Here's what happens when a browser loads a website with a <script> tag on it:

  1. Fetch the HTML page (e.g. index.html)
  2. Begin parsing the HTML
  3. The parser encounters a <script> tag referencing an external script file.
  4. The browser requests the script file. Meanwhile, the parser blocks and stops parsing the other HTML on your page.
  5. After some time the script is downloaded and subsequently executed.
  6. The parser continues parsing the rest of the HTML document.

Step #4 causes a bad user experience. Your website basically stops loading until you've downloaded all scripts. If there's one thing that users hate it's waiting for a website to load.

Why does this even happen?

Any script can insert its own HTML via document.write() or other DOM manipulations. This implies that the parser has to wait until the script has been downloaded and executed before it can safely parse the rest of the document. After all, the script could have inserted its own HTML in the document.

However, most JavaScript developers no longer manipulate the DOM while the document is loading. Instead, they wait until the document has been loaded before modifying it. For example:

<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>

JavaScript:

// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

Because your browser does not know my-script.js isn't going to modify the document until it has been downloaded and executed, the parser stops parsing.

Antiquated recommendation

The old approach to solving this problem was to put <script> tags at the bottom of your <body>, because this ensures the parser isn't blocked until the very end.

This approach has its own problem: the browser cannot start downloading the scripts until the entire document is parsed. For larger websites with large scripts and stylesheets, being able to download the script as soon as possible is very important for performance. If your website doesn't load within 2 seconds, people will go to another website.

In an optimal solution, the browser would start downloading your scripts as soon as possible, while at the same time parsing the rest of your document.

The modern approach

Today, browsers support the async and defer attributes on scripts. These attributes tell the browser it's safe to continue parsing while the scripts are being downloaded.

async

<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>

Scripts with the async attribute are executed asynchronously. This means the script is executed as soon as it's downloaded, without blocking the browser in the meantime.
This implies that it's possible that script 2 is downloaded and executed before script 1.

According to http://caniuse.com/#feat=script-async, 97.78% of all browsers support this.

defer

<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>

Scripts with the defer attribute are executed in order (i.e. first script 1, then script 2). This also does not block the browser.

Unlike async scripts, defer scripts are only executed after the entire document has been loaded.

According to http://caniuse.com/#feat=script-defer, 97.79% of all browsers support this. 98.06% support it at least partially.

An important note on browser compatibility: in some circumstances, Internet Explorer 9 and earlier may execute deferred scripts out of order. If you need to support those browsers, please read this first!

(To learn more and see some really helpful visual representations of the differences between async, defer and normal scripts check the first two links at the references section of this answer)

Conclusion

The current state-of-the-art is to put scripts in the <head> tag and use the async or defer attributes. This allows your scripts to be downloaded ASAP without blocking your browser.

The good thing is that your website should still load correctly on the 2% of browsers that do not support these attributes while speeding up the other 98%.

References

  • async vs defer attributes
  • Efficiently load JavaScript with defer and async
  • Remove Render-Blocking JavaScript
  • Async, Defer, Modules: A Visual Cheatsheet

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

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.

The 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 unnecessary 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 recommended practice, it might not always be harmless. When dealing with CMSes, 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

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 an extreme bounce rate. In this case I'd consider putting the script in the head.

If you put resource hints at the beginning, 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.

placing script tags right before /body doesn't work as expected

...so the script runs after the page content is fully loaded.

Correct, all the elements above it are parsed and in the DOM — but, the browser may or may not have had a chance to render them yet. To give it a chance to do so, through a very small delay into your code.

    <script>
setTimeout(function() {
alert('hey there');
}, 50);
</script>
</body>

Live Example:

<p>hello world!</p><script>setTimeout(function() {    alert('hey there');}, 50);</script>

Why my code doesn't work when the script tag is in the head tag?

First, the HTML get parsed from top to bottom, So Whatever encounter first will get run.

If you put script tag at the end of the head tag then It will run first before the HTML body so you can't set width because when you used

document.getElementById("video")

It would return null so you can't set properties on null. Because at the time of this statement the element doesn't exist.

<html>

<head>
<script>
const heading = document.querySelector("h1");
console.log(heading); // null
</script>
</head>

<body>
<h1> This is heading</h1>
</body>

</html>

What happens when you place javascript after the closing body tag?

Javascript runs when it's encountered in the markup. If you are manipulating the page DOM then the nodes you want to affect must exist when the javascript runs, which is why people place the scripts after all of the page content.

Either before or after the close </body> tag should make no difference, and in my experience it doesn't, because the script is encountered and therefore run at essentially the same time, after the DOM has been built.

But see the suggested duplicate for reasons to put it inside the body.

Why scripts at the end of body tag

Scripts, historically, blocked additional resources from being downloaded more quickly. By placing them at the bottom, your style, content, and media could download more quickly giving the perception of improved performance.

Further reading: The async and defer attributes.



Related Topics



Leave a reply



Submit