18

I am looking for something similar to jQuery image lazy load plugin, but for iframes.

alex
  • 479,566
  • 201
  • 878
  • 984
Steve
  • 4,946
  • 12
  • 45
  • 62
  • 1
    Best bet is to just not add the iframe to the DOM until you want to load it, no chance of confusion then... – DaveRandom Aug 23 '11 at 00:05
  • The iframe is hard coded into the DOM. I don't have the option to manually insert them, otherwise this would've been the easiest route. – Steve Aug 23 '11 at 00:29

6 Answers6

24

This worked for me.

var iframes = $('iframe');

$('button').click(function() {
    iframes.attr('src', function() {
        return $(this).data('src');
    });
});

iframes.attr('data-src', function() {
    var src = $(this).attr('src');
    $(this).removeAttr('src');
    return src;
});

jsFiddle.

alex
  • 479,566
  • 201
  • 878
  • 984
  • 1
    So if `src` is hard coded in html of the DOM, change them to `data-src` then on demand change it to `src` to load the content? Also, my event is not based on scroll, but rather on click that `:target`s the containing `div`. – Steve Aug 23 '11 at 00:31
  • I tried it and it didn't work (see edit above), hence down vote. Got some code that works? Would be happy to give it a try and change my vote and select this as the answer. I do appreciate your response either way and I like the logic behind your explanation. I just want a working solution to be the answer. – Steve Aug 23 '11 at 17:11
4

A similar question was recently posted specific to iFrames with Twitter Bootstrap-based tabs, which I answered using a technique I'm calling Lazy Loading of iFrames. The js/jquery is as follows; see the full code including html markup in the fiddle or on my response to the OP:

<script>
$('#myTabs').bind('show', function(e) {  

// identify the tab-pane
paneID = $(e.target).attr('href');

// get the value of the custom data attribute to use as the iframe source
src = $(paneID).attr('data-src');

//if the iframe on the selected tab-pane hasn't been loaded yet...
if($(paneID+" iframe").attr("src")=="")
{
    // update the iframe src attribute using the custom data-attribute value
    $(paneID+" iframe").attr("src",src);
}
});
</script>
Community
  • 1
  • 1
technoTarek
  • 3,218
  • 2
  • 21
  • 25
2

<iframe loading="lazy"

When implemented, this feature will allow lazy loading when the iframe enters the viewport without any JavaScript!

There is also an analogous feature for images: How do you make images load lazily only when they are in the viewport?

For iframes, I'm not sure what is the status, but it does seem like there is an intention to enable it as well:

To observe this in action, open the "Network" tab of your developer tools before running the snippet below. If your browser implements the feature, you can clearly see new network requests as you scroll down to the next iframe!

Test outcomes:

  • Chromium 81: works, loads on hover
  • Firefox 77: fails, loads all at once

document.getElementById('load-now').addEventListener('click', function(){
  for (const img of document.getElementsByTagName('iframe')) {
    img.loading = 'eager';
  }
});
.separator {
    height: 1000px;
    width: 100px;
    border: 5px solid red;
}
img {
    height: 340px;
    border: 5px solid black;
}
#load-now {
  border: 5px solid black;
}
<div id="load-now">Click me to load all images now!</div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/Donald_Trump"></iframe></div>
<div class="separator"></div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/Barack_Obama"></iframe></div>
<div class="separator"></div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/George_W._Bush"></iframe></div>
<div class="separator"></div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/Bill_Clinton"></iframe></div>
<div class="separator"></div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/George_H._W._Bush"></iframe></div>
<div class="separator"></div>
<div><iframe loading="lazy" height="340" src="https://en.wikipedia.org/wiki/Ronald_Reagan"></iframe></div>

YouTube videos

For YouTube embedded video iframe more specifically: Lazy Load youtube video from iframe API

On Chromium 81, it also works on jsfiddle: https://jsfiddle.net/cirosantilli/3p0tk5nc but didn't work here on Stack Overflow. I'm not sure why. Removing the loading="lazy" makes no difference, so I think it fails for some other reason.

Keep in mind that embedding YouTube videos on a local HTML file also fails randomly to me which makes testing harder: Embed Youtube code is not working in HTML

document.getElementById('load-now').addEventListener('click', function(){
  for (const img of document.getElementsByTagName('iframe')) {
    img.loading = 'eager';
  }
});
.separator {
    height: 1000px;
    width: 100px;
    border: 5px solid red;
}
img {
    height: 340px;
    border: 5px solid black;
}
  #load-now {
  border: 5px solid black;
  }
<div id="load-now">Click me to load all images now!</div>
<div><iframe width="560" height="315" loading="lazy"  src="https://www.youtube.com/embed/j_fl4xoGTKU" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
<div class="separator"></div>
<div><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/TQ5k2u25eI8" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
<div class="separator"></div>
<div><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/FOwYDlay8rI" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
<div class="separator"></div>
<div><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/MRhAljmHq-o" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
<div class="separator"></div>
<div><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/wAQxIla7F68" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
<div class="separator"></div>
<div><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/_6D05gCWh_I" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></iframe></div>
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

If you want to do this in WordPress

Here is an automatic, request reducing, solution

In WordPress plugin form

Here is a WordPress plugin you can download and manually install via the WordPress plugin repository. I created this today just to handle this situation. No changes to content are needed, this works automatically once activated on any and all iframes.

https://wordpress.org/plugins/lowermedia-iframes-on-demand/

9ete
  • 3,692
  • 1
  • 34
  • 32
0

You could always intialize the src attribute to about:blank and then when your click event fires, set the src attribute to the URL you want to navigate to.

nickytonline
  • 6,855
  • 6
  • 42
  • 76
  • the iframe `src` is hard coded in the HTML of the DOM and don't want to do too many DOM manipulation by replacing it with about:blank and then replacing it back with the URL (which need to be stored as a variable). – Steve Aug 23 '11 at 17:29
0

Can you set the src to about:blank? Like this?

http://jsfiddle.net/MaUfH/

wightnoise
  • 73
  • 2
  • 6
  • The `iframe` is embedded into the HTML of the page and loaded on page load, while your example loads the `iframe` onClick. This doesn't work in my case. – Steve Aug 23 '11 at 17:32