0

I have read at https://web.dev/howbrowserswork/#The_main_flow that printing the website is a gradual process, and will not wait before the DOM/CSS/RENDER/LAYOUT tree is parsed completely.

It's important to understand that this is a gradual process. For a better user experience, the rendering engine will try to display contents on the screen as soon as possible. It will not wait until all HTML is parsed before starting to build and layout the render tree. Parts of the content will be parsed and displayed, while the process continues with the rest of the content that keeps coming from the network.

I tried to find an example to test it. For the following HTML, I would expect that the green box is printed first, then JS is blocked and next the yellow box is rendered:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <div style="height:300px;width:700px;background-color:green"></div>
    <script>
    function sleep(milliseconds) {
      const date = Date.now();
      let currentDate = null;
      do {
        currentDate = Date.now();
      } while (currentDate - date < milliseconds);
    }

    console.log("Hello");
    sleep(2000);
    console.log("World!");
    </script>    
    <div style="height:300px;width:700px;background-color:yellow"></div>
  </body>
</html>

However, testing this on Chrome and Firefox, nothing will be shown and after two seconds the green and a yellow box will show at the same time.

Why is my example not printing as a gradual process? Can you provide an example of a gradual printing process?

Manoj Agrawal
  • 429
  • 3
  • 10
Adam
  • 25,960
  • 22
  • 158
  • 247
  • You're blocking the browser's main thread by calling your `sleep` function. The browser engine does not stop your JavaScript execution to render the page for the client. If it'd do this, then all kind of render scripts on the web would never be able to perform like they should. – Nora Jul 24 '22 at 11:30
  • This is also why some browsers may force close a website if it blocks the thread for too long, e.g. causing an infinitive iteration, etc. – Nora Jul 24 '22 at 11:31
  • @Nora can you give an example where gradual printing takes place? Meaning that something is printed before the DOM tree is rendered? – Adam Jul 24 '22 at 11:42
  • 3
    Instead of your script, add a script-tag that loads a script-file and have the server respond really slow (ie put your sleep on the server side). Rendering can be done in stages, but it is a very expensive. So if there is continually coming in new information to the document most browsers will probably wait instead of wasting resources on something that will be obsolete in a second. Waiting for an external resource however should give it ample time to fire off a render while not doing much else though. In the end it is probably completely browser dependent though. – Karl-Johan Sjögren Jul 24 '22 at 11:56

1 Answers1

0

as others have said you are blocking rendering with that code. the better method for what you are trying to accomplish, may be to set a timeout in javascript, then add the element you want added after the delay by manipulating the DOM.

setTimeout( () => {
   const elem = document.createElement('div');
   elem.style.cssText = 'height:300px;width:700px;background-color:yellow';
   document.body.appendChild(elem);
}, 2000);

another even better method might be to use CSS to show a hidden element after a set time using CSS animations.

yet another option would be to use a class to hide the element from rendering display: none, then remove that class, or add another class that changes display, using javascript and a timeout.

dqhendricks
  • 19,030
  • 11
  • 50
  • 83
  • Using `setTimeout` would not make sense for my test, as this is async and the DOM tree would be immediately rendered. I want to have the JS blocking the DOM tree parsing, and still see a partial of the DOM printed a stated as stated in the cited reference: `the rendering engine will try to display contents on the screen as soon as possible. It will not wait until all HTML is parsed before starting to build and layout the render tree.` – Adam Jul 27 '22 at 04:00
  • Same goes for your css example, when you use js timeout to unhide an element, the DOM tree will be already rendered. – Adam Jul 27 '22 at 04:02
  • @Adam I don't understand exactly what the difference is, if the end-user effect is the same. But if you have some use case for this somehow, then server side delaying of output is your only option as far as I can tell. Or maybe using AJAX to pull more content as needed with further requests to the server. Browsers aren't designed to delay rendering for some block of in page code, as that would tend to lead to bad user experiences. And you can't stop and continue the download with client side code. Perhaps if I understood why (what the use case for this is) I could better help you. – dqhendricks Jul 27 '22 at 16:50