138

I have an iframe that loads a third party website which is extremely slow to load.

Is there a way I can display a loading message while that iframe loads the user doesn't see a large blank space?

PS. Note that the iframe is for a third party website so I can't modify / inject anything on their page.

Preview
  • 35,317
  • 10
  • 92
  • 112
Jacob
  • 6,317
  • 10
  • 40
  • 58

11 Answers11

284

I have done the following css approach:

<div class="holds-the-iframe"><iframe here></iframe></div>

.holds-the-iframe {
  background:url(../images/loader.gif) center center no-repeat;
}
Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
Christina
  • 34,296
  • 17
  • 83
  • 119
  • 1
    This worked perfect for my cases. The one chosen answer did not work for me because I was loading iFrame only when a tab was being clicked. But this one displayed elegantly while loading iFrame source. But too bad that this wasn't chosen as the answer because Jacob asked for jQuery solution... – dance2die Jan 21 '15 at 16:07
  • 30
    This does not work well if the iframe you are loading has a transparent background. You can still see the loading gif once the iframe loads! – Westy92 Jun 26 '15 at 15:31
  • 3
    @Christna This trick is not working for IE-11. Is there any hack? – mmuzahid Sep 19 '17 at 09:41
  • 3
    With the iframe onload function you can remove the CSS background image. – Hugo Cox Oct 20 '17 at 00:09
  • 1
    Great answer. It works. You also better adding some height so the loader will be easily visible. – Raz Mar 01 '18 at 14:11
  • @Christina it's working fine in the Firefox but issue with the Chrome browser. Loader is not displaying on the Chrome. Any solution. Please help. – Nishant May 11 '18 at 06:59
  • Thank you. As others mentioned, this does not work for IE11. – Robert Smith Dec 02 '19 at 19:55
  • is there a way to set the height? I see that Raz also suggested that would help. How do you do it? – AppDreamer Jan 14 '20 at 15:38
  • I figured it out... made two minor changes... background:url(./../../../assets/images/loader.gif) top center no-repeat; background-size: 20vh; by the way... the ../.. I show here is correct for latest Angular if you are calling it from your component's .css. Thanks for the great tip! – AppDreamer Jan 14 '20 at 16:12
35

I think that this code is going to help:

JS:

$('#foo').ready(function () {
    $('#loadingMessage').css('display', 'none');
});
$('#foo').load(function () {
    $('#loadingMessage').css('display', 'none');
});

HTML:

<iframe src="http://google.com/" id="foo"></iframe>
<div id="loadingMessage">Loading...</div>

CSS:

#loadingMessage {
    width: 100%;
    height: 100%;
    z-index: 1000;
    background: #ccc;
    top: 0px;
    left: 0px;
    position: absolute;
}
Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
Minko Gechev
  • 25,304
  • 9
  • 61
  • 68
  • I understand why you hide `#loadingMessage` when `load` fires, but why do you also hide it on `ready`? Isn't that too early? – teedyay Jul 25 '12 at 10:30
  • 1
    It depends on the user's needs. If he don't need all images to be loaded before he hide the loading message then he won't need the on load callback. – Minko Gechev Jul 25 '12 at 12:55
  • 5
    @OZ_ it is not hard to turn the code above to vanilla javascript by using `addEventListener` and use `querySelector` + the `style`s property :-). In addition to that, the author of the question have tagged is as `jquery`. Can't get why was your message? :-) – Minko Gechev Mar 26 '15 at 16:40
27

If it's only a placeholder you are trying to achieve: a crazy approach is to inject text as an svg-background. It allows for some flexbility, and from what I've read the browser support should be fairly decent (haven't tested it though):

  • Chrome >= 27
  • FireFox >= 30
  • Internet Explorer >= 9
  • Safari >= 5.1

html:

<iframe class="iframe-placeholder" src=""></iframe>

css:

.iframe-placeholder
{
   background: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100% 100%"><text fill="%23FF0000" x="50%" y="50%" font-family="\'Lucida Grande\', sans-serif" font-size="24" text-anchor="middle">PLACEHOLDER</text></svg>') 0px 0px no-repeat;
}

What can you change?

Inside the background-value:

  • font size: look for font-size="" and change the value to anything you want

  • font color: look for fill="". Don't forget to replace the # with %23 if you're using hexadecimal color notation. %23 stands for a # in URL encoding which is necessary for the svg-string to be able to be parsed in FireFox.

  • font family: look for font-family="" remember to escape the single quotes if you have a font that consists of multiple words (like with \'Lucida Grande\')

  • text: look for the element value of the text-element where you see the PLACEHOLDER string. You can replace the PLACEHOLDER string with anything that is url-compliant (special characters need to be converted to percent notation)

Example on fiddle

Pros:

  • No extra HTML-elements
  • No js
  • Text can easily (...) be adjusted without the need of an external program
  • It's SVG, so you can easily put any SVG you want in there.

Cons:

  • Browser support
  • It's complex
  • It's hacky
  • If the iframe-src doesn't have a background set, the placeholder will shine through (which is not inherent to this method, but just standard behaviour when you use a bg on the iframe)

I would only recommend this only if it's absolutely necessary to show text as a placeholder in an iframe which requires a little bit of flexbility (multiple languages, ...). Just take a moment and reflect on it: is all this really necessary? If I had a choice, I'd go for @Christina's method

Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
Pascalculator
  • 870
  • 1
  • 10
  • 17
14

An alternative solution.

<iframe srcdoc="Loading..." onload="this.removeAttribute('srcdoc')" src="https://example.com"></iframe>

Note that srcdoc attribute can have any HTML markup. So you can apply custom styles to the message.

<iframe id="example" src="https://example.com"></iframe>
<script>
  const iframe = document.getElementById('example');
  iframe.srcdoc = '<!DOCTYPE html><p style="color: green;">Loading...</p>';
  iframe.addEventListener('load', () => iframe.removeAttribute('srcdoc'));
</script>
ya.teck
  • 2,060
  • 28
  • 34
8

Here's a quick solution for most of the cases:

CSS:

.iframe-loading { 
    background:url(/img/loading.gif) center center no-repeat; 
}

You can use an animated loading GIF if you want to,

HTML:

<div class="iframe-loading">
    <iframe src="http://your_iframe_url_goes_here"  onload="$('.iframe-loading').css('background-image', 'none');"></iframe>
</div>

Using the onload event you can remove the loading image after the source page is loaded inside your iframe.

If you are not using jQuery, just put an id into the div and replace this part of code:

$('.iframe-loading').css('background-image', 'none');

by something like this:

document.getElementById("myDivName").style.backgroundImage = "none";

All the best!

David Toledo
  • 484
  • 6
  • 13
6
$('iframe').load(function(){
      $(".loading").remove();
    alert("iframe is done loading")
}).show();


<iframe src="http://www.google.com" style="display:none;" width="600" height="300"/>
<div class="loading" style="width:600px;height:300px;">iframe loading</div>
Salt Hareket
  • 764
  • 7
  • 18
  • This isn't necessarily a good solution for an iframe that is loading on a third party website, as they may not have jQuery on their page. – Luke Apr 16 '17 at 18:55
4

You can use below code .

 iframe {background:url(../images/loader.gif) center center no-repeat; height: 100%;}
Mobarak Hossen
  • 767
  • 5
  • 7
4

Yes, you could use a transparent div positioned over the iframe area, with a loader gif as only background.

Then you can attach an onload event to the iframe:

 $(document).ready(function() {

   $("iframe#id").load(function() {
      $("#loader-id").hide();
   });
});
Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
maxijb
  • 541
  • 4
  • 13
1

I have followed the following approach

First, add sibling div

$('<div class="loading"></div>').insertBefore("#Iframe");

and then when the iframe completed loading

$("#Iframe").load(function(){
   $(this).siblings(".loading-fetching-content").remove(); 
  });
gaurav
  • 309
  • 2
  • 7
0
<!DOCTYPE html>
<html>
<head>
<title>jQuery Demo - IFRAME Loader</title>
<style>
#frameWrap {
    position:relative;
    height: 360px;
    width: 640px;
    border: 1px solid #777777;
    background:#f0f0f0;
    box-shadow:0px 0px 10px #777777;
}

#iframe1 {
    height: 360px;
    width: 640px;
    margin:0;
    padding:0;
    border:0;
}

#loader1 {
    position:absolute;
    left:40%;
    top:35%;
    border-radius:20px;
    padding:25px;
    border:1px solid #777777;
    background:#ffffff;
    box-shadow:0px 0px 10px #777777;
}
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>

<div id="frameWrap">
<img id="loader1" src="loading.gif" width="36" height="36" alt="loading gif"/>
<iframe id="iframe1" src="https://bots.actcorp.in/ACTAppChat/chat?authtext=test@user8.com&authToken=69d1afc8d06fb97bdb5a9275edbc53b375c3c7662c88b78239ba0cd8a940d59e" ></iframe>
</div>
<script>
    $(document).ready(function () {
        $('#iframe1').on('load', function () {
            $('#loader1').hide();
        });
    });
</script>

</body>
</html>
Romi
  • 31
  • 2
-1

You can use as below

$('#showFrame').on("load", function () {
        loader.hide();
});