Kharlamov Anton
Kharlamov Anton

Reputation: 99

Browsers react differently to <script> inside <body>

Here is the problem I can't understand. Look at this JS code:

<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>
  <p>The Beginning...</p>
  <script>
    alert('Hello, Wolrd!');
  </script>
  <p>...The End Of Doc</p>
</body>

</html>

So the problem is that I do not understand why The Beginning paragraph isn't loaded/visible before the <script> tag. In almost all tutorials it's explained that the browser loads all HTML before it meets script, then when the script is met the browser starts working in script's compilation mode and then when the script ends browser returns in HTML mode.

But on practic it seems that it behaves differently, as The Beginning text appears only after script alert:

enter image description here

Could please someone explain why is that happening?


PS: Only Firefox behaves as described in the tutorials.

Upvotes: 9

Views: 215

Answers (3)

T.J. Crowder
T.J. Crowder

Reputation: 1074228

The elements from before the script have been created and added to the DOM, but the browser hasn't had a chance to render them (update the page display to show them) before the alert brings the whole UI thread to a screeching halt. The browser is required to have created the elements and added them to the DOM; it is not required to have rendered them yet. Some will, some won't. Neither is "wrong."

We can readily prove that the first paragraph exists by looking for it and even reading its text:

<p>The Beginning...</p>
<script>
  alert("Hello, World! First paragraph's text: " + document.querySelector("p").textContent);
</script>
<p>...The End Of Doc</p>

Upvotes: 4

Ahmad Maleki
Ahmad Maleki

Reputation: 1495

It has to behave as the tutorials say; So I think it's browsers' weakness according to the following scenarios:

We have this CodePen (that you linked in a comment) with the following code:

<p id="one">
    The Beginning...</p>
<script>
    alert(document.getElementById('one').innerHTML);
</script>
<p id="two">...The End Of Doc</p>

Scenario 1 :

Follow the link and wait for the code to load. As you said, alert pops up but The Beginning and The End are not shown. After you close the alert, the text is visible.

Scenario 2 (Only happens in Chrome so far. Safari behaves like scenario 1) :

Open the link in a new tab without following it (You can use Ctrl + Right Click or Mouse Wheel Click). Wait for about 10 seconds (You'll see a small blue dot in CodePen's favIcon). Now open the CodePen tab and BOOM! you'll see both the alert and The Beginning/The End Text.

This makes me think that Chrome is not working as it is supposed to.

Upvotes: -1

marc4ndrew
marc4ndrew

Reputation: 41

Because the JavaScript execute immediately before the DOM completed parsing (that's the 'problem' that ready solves). You can include an event listener to check if your DOM is ready

<script>
var callback = function() {
    alert( 'Hello, Wolrd!' );
};

if(document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
    callback();
} else {
    document.addEventListener("DOMContentLoaded", callback);
}
</script>

But the simplest thing you can do is to move your <script> tag to the end before </body>.

<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  <p>The Beginning...</p>


  <p>...The End Of Doc</p>

  <script>
    alert( 'Hello, Wolrd!' );
  </script>
</body>

</html>

Upvotes: -2

Related Questions