Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load an iframe without blocking onload or waiting for onload

Suppose I have this page:

<h1>Hello, world!</h1>
<iframe src="https://example.com/test.html"></iframe>

And test.html contains this:

<img src="huge.png" />

huge.png is 100mb for some reason.

I have no control over test.html, but I must include the iframe in my page.

Is there a way to load the iframe without

  1. blocking my page's onload event OR
  2. waiting until my page's onload event to set the iframe's src attribute

I want #1 because I don't want JS on my page to have to wait for example.com's slow image.

I want #2 because I want to start loading example.com's content ASAP.

There are two similar questions.

  • is there a way to load an iframe asynchronously
  • Javascript preload iframe without blocking the browser

This is why they aren't duplicates:

  1. Neither is clear what it means to "block" loading - I specify the onload event.
  2. Neither specifies that I don't have control over the iframe's contents (which the first answer on #2 assumes).
  3. Neither specifies that setting the src attribute after onload is not an option (which several answers on #1 assume).

While it's possible that answers to those questions could answer this one, neither is worded in such a way that the answer must answer this question.

like image 933
crenshaw-dev Avatar asked Dec 02 '18 17:12

crenshaw-dev


People also ask

Does iframe block page load?

It shouldn't block. If you want the main page to fully load first (eg, main page's images before iframe content) then you'll have to use a bit of javascript to set the url of the iframe, like <body onload="javascript:..."> Main document's onload won't fire until all iframes have been loaded.

How do I make sure iframe is loaded?

To check if iframe is loaded or it has a content with JavaScript, we can set the iframe's onload property to a function that runs when the iframe is loaded. document. querySelector("iframe"). onload = () => { console.

Does iframe have onload?

If you want to run JavaScript when an iframe has finished loading, you can either: include code in the iframe tag's onload attribute, or. assign code to the iframe's onload event handler property.


2 Answers

You can use Window: DOMContentLoaded event as suggested by charlietfl in the comments; it does not get blocked by resources/assets loading:

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

Here is a demo snippet that loads an external iFrame that has a 2MB JPEG image; when you run it, you'll see that DOMContentLoaded get to trigger before the iFrame fully loads and it runs custom Javascript; then when the iFrame is done loading, the load event on the iFrame is called and we update a status text.

// On DOMContentLoaded set status text and start an ASCII animation
window.addEventListener('DOMContentLoaded', (event) => {
  document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code';

  const animation = new animascii({
      src: [
          ["0-----", "-----0"],
          ["-0----", "----0-"],
          ["--0---", "---0--"],
          ["---0--", "--0---"],
          ["----0-", "-0----"],
          ["-----0", "0-----"]
      ],
      display: document.getElementById("ascii-animation"),
      repeat: -1,
      delay: 120,
      font_size: 20
  }, function() {
      alert("Done!");
  });
});

// On iframe load event set status text
document.getElementsByTagName('iframe')[0].addEventListener('load', function() {
  document.getElementById('iframe-status').textContent = 'IFrame fully loaded';
});
iframe { width: 600px; height: 400px; }
h2 span { color: blue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rot.js/0.6.0/rot.min.js"></script>
<script src="https://www.cssscript.com/demo/ascii-animation-library-pure-javascript-animascii/animascii.js"></script>

<h2>DOM/JS status: <span id="js-status">(loading...)</span></h2>
<h2>IFrame status: <span id="iframe-status">(loading...)</span></h2>

<h3>Demo JS to check that JS is running after DOMContentLoaded and before iFrame finish loading</h3>
<div id="ascii-animation"></div>

<iframe src="https://zikro.gr/dbg/so/53583045/iframe.php"></iframe>

Of course you can set the iFrame src attribute on load, but that is already covered by the questions you're linking:

window.addEventListener('load', (event) => {
  document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code';
  document.getElementById('iframe-status').textContent = '(loading...)';
  document.getElementsByTagName('iframe')[0].setAttribute('src', 'https://zikro.gr/dbg/so/53583045/iframe.php');
});

document.getElementsByTagName('iframe')[0].addEventListener('load', (event) => {
  document.getElementById('iframe-status').textContent = 'IFrame fully loaded';
});
iframe { width: 600px; height: 400px; }
h2 span { color: blue; }
<h2>DOM/JS status: <span id="js-status">(loading...)</span></h2>
<h2>IFrame status: <span id="iframe-status">(not started yet)</span></h2>

<iframe></iframe>
like image 164
Christos Lytras Avatar answered Oct 25 '22 20:10

Christos Lytras


A different and somewhat-easier trick: do the load as usual, but also include

<link rel="prefetch" href="https://example.com/test.html">

in your page's <head>.

The browser will start fetching test.html (or huge.png) for you.

It doesn't even require the iframe to exist, you can put it in any page. If you want, you can have the browser start loading the external resource before it's even on the specific page that needs it.

The detailed time depends on the browser's decision, of course, but at the end of the day that's true for all async requests -- and you can put that prefetch first thing after the doctype stuff.

like image 29
Jacopo Avatar answered Oct 25 '22 18:10

Jacopo