59

I cannot get z-index working on a iframe that contains a pdf file with IE8. It works with Google Chrome.

Example (JSFiddle):

HTML

<div id="div-text">
      <div id="shouldBeOnTop">my text that should be on top</div>
</div>
<div id="div-frame">
    <iframe src="http://legallo1.free.fr/french/CV_JLG.pdf" width="200" height="200"/>
</div>

CSS

#div-text{
    position:relative;
    left:210px;
    top:20px
}

#shouldBeOnTop{
    position:relative;
    right:60px;
    background-color:red;
    width:100px;
    z-index:2;
}

#div-frame{
    position:relative;
     z-index:1;
}
user247702
  • 23,641
  • 15
  • 110
  • 157
Corinne Kubler
  • 2,072
  • 5
  • 22
  • 34
  • Like the same issue discussed in http://stackoverflow.com/questions/12407194/css-drop-down-div-not-working-in-ie9 – sureshunivers Oct 19 '12 at 06:40
  • 1
    Please note, the PDF link used in the JSFiddle example returns a custom 404 error page which in the example with its small viewport you wouldn't know is not the PDF file. I couldn't figure out why, whilst playing with that example, I got different results when pointing at the actual generated PDF file I want to view! – Matthew Wise Aug 16 '16 at 08:32
  • i have the exact same problem. – Shaik Bajivali Jul 04 '20 at 07:06

4 Answers4

90

Update: Matthew Wise has a really clever alternative solution which you should consider—especially if you're having trouble with my approach or dislike ugly hacks!


There is a way to cover windowed elements in IE with other elements, but you're not going to like it.

Background: windowed and windowless elements

Legacy IE categorises elements into two types: windowed and windowless.

Regular elements like div and input are windowless. They are rendered by the browser itself in a single MSHTML plane and respect each other's z-order.

Elements rendered outside of MSHTML are windowed; for example, select (rendered by the OS) and ActiveX controls. They respect each other's z-order, but occupy a separate MSHTML plane that is painted on top of all windowless elements.

The only exception is iframe. In IE 5, iframe was a windowed element. This was changed in IE 5.5; it is now a windowless element, but for backwards compatibility reasons it will still draw over windowed elements with a lower z-index

In other words: iframe respects z-index for both windowed and windowless elements. If you position an iframe over a windowed element, any windowless elements positioned over the iframe will be visible!

What this means

The PDF will always be painted on top of the regular page content—like select elements were until IE 7. The fix is to position another iframe between your content and the PDF.

Demo

jsFiddle: http://jsfiddle.net/Jordan/gDuCE/

Code

HTML:

<div id="outer">
    <div id="inner">my text that should be on top</div>
    <iframe class="cover" src="about:blank"></iframe>
</div>

<iframe id="pdf" src="http://legallo1.free.fr/french/CV_JLG.pdf" width="200" height="200"></iframe>

CSS:

#outer {
    position: relative;
    left: 150px;
    top: 20px;
    width: 100px;
    z-index: 2;
}

    #inner {
        background: red;
    }

    .cover {
        border: none;
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        z-index: -1;
    }

#pdf {
    position: relative;
    z-index: 1;
}

Support

This has been tested and should work in IE 7–9. If you feel persnickety about it showing up in the DOM for other browsers, you can add it with JavaScript or wrap it in an IE-only conditional comment:

<!--[if IE]><iframe class="cover" src="about:blank"></iframe><![endif]-->
Jordan Gray
  • 16,306
  • 3
  • 53
  • 69
  • 1
    Is there a particular property to investigate to see if this feature would be triggered (e.g. $.support or a modernizr property)? – mlhDev Jan 31 '14 at 12:33
  • @Matthew Good question! The issue is unique to IE because of it's idiosyncratic handling of `z-index`, but I'll think on it and see if I can come up with a more direct test. – Jordan Gray Jan 31 '14 at 13:53
  • @Matthew Oh, and in case you need this in short order and aren't sure where to start: the first idea that occurs to me is to generate an `iframe` and a `div` with a higher z-index, position both at the same position on the page, then use `document.elementFromPoint` with those coordinates to find out which is on top. :) – Jordan Gray Jan 31 '14 at 14:37
  • @Matthew I'll need to test it in an IE VM, but I've made a start at [a Modernizr test](http://jsfiddle.net/Jordan/cx6XJ/) for the functionality. Not yet sure that it's working correctly, so I would hold off on using it for the time being. – Jordan Gray Feb 02 '14 at 04:36
  • (IETester indicates that it's not working correctly, BTW. :( ) – Jordan Gray Feb 02 '14 at 04:43
  • I added only the iframe with the cover class to my code and it worked. Thanks! – Hashim Akhtar Jun 10 '14 at 09:06
  • Works well, unfortunately however causes a flicker on scroll with my fixed element. +1 none-the-less for the solution. – crowebird Jun 27 '14 at 19:46
  • I have the same problem in IE11 with Bootstrap 3 menu. Have you ever fix this kind of problem? – xerius May 28 '15 at 17:11
  • 2
    I might add that, after testing this, this works just as well in IE11, as we had a hell of a time getting a jQuery UI modal to show over a pdf in an iframe. The only even potential issue is the modal flickers as the page is scrolled, as mentioned above, but at least it works. – Kendra Dec 04 '15 at 14:27
  • 1
    @Kendra Hmm—does forcing hardware acceleration, e.g. via `(-ms-)transform: translateZ(0);` on the modal element, have any impact on the flickering? – Jordan Gray Dec 04 '15 at 19:28
  • 1
    Thanks for the suggestion, Jordan- No, it did not, at least for our app. It shouldn't matter too much in this case at least. The only modal (at least currently) that has this issue is one prompting the user to click a button to stay logged in. – Kendra Dec 04 '15 at 19:42
  • 2
    Maybe I've done it wrong, but with this solution, I can see my div over the PDF, but I can't interact with it (E.g. click events) because the iFrame is in the way. – Russell Horwood Dec 21 '16 at 11:21
  • @NineTails Hmm, that's interesting. Will need to test this; very unexpected behaviour. Thanks for bringing it up! – Jordan Gray Dec 21 '16 at 23:48
  • 2
    @JordanGray It turned out my 'inner' div was being covered with my 'cover' iframe, I raised it's z-index and I got the desired result. Thanks. – Russell Horwood Dec 22 '16 at 09:46
  • @NineTails Haha, thank goodness; I was preparing to be so annoyed at IE again for doing something weird! :D – Jordan Gray Dec 22 '16 at 17:43
  • 3
    windowed and windowless, I learned something awful today about IE. Hail Chrome. – JoshYates1980 Mar 02 '17 at 20:15
  • @JoshYates1980 Indeed—the less I have to learn about IE, the happier I am! – Jordan Gray May 18 '17 at 15:46
  • This is not working in IE11. DO you know any solution for this ? – Sanjay Gohil Mar 28 '18 at 12:42
  • @SanjayGohil I'm afraid not; is it definitely the same problem, or could it just be e.g. `z-index` being overridden? – Jordan Gray May 14 '18 at 12:31
  • @JordanGray - using Google Doc Viewer is free for commercial use? e.g. docs.google.com/gview?embedded=true&url=pdfURL – Ankush Jain Jun 15 '18 at 06:54
8

The workaround with the additional IFRAME does work in simple cases but I have spent a morning trying to get the overlay to respect transparency. Basically our application has modal popups whereby a full-window overlay behind the popups is rendered 'greyed out' (background colour black, opacity 0.25) to indicate to the user that the pop-ups are modal. With the workaround, the embedded PDF view never gets greyed out with the rest of the window so still looks 'active' and indeed you can still interact with the PDF viewer.

Our solution is to use Mozilla's pdf.js library: https://github.com/mozilla/pdf.js/ - embedding an IFRAME pointing at the test URL http://mozilla.github.com/pdf.js/web/viewer.html?file=compressed.tracemonkey-pldi-09.pdf works straight out of the box respecting z-index, transparency, the lot, no hacks required! Seems that they use their own rendering engine which generates standard HTML representing the content of the PDF.

Matthew Wise
  • 2,639
  • 26
  • 23
  • 1
    This is a really original solution, Matt—wish it was more prominent! – Jordan Gray Jun 28 '18 at 13:55
  • It's important to note that IE will no longer be supported as of version 2.6.347 as per https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#which-browsers-are-supported – Ian Kemp Nov 09 '20 at 12:30
4

I Had been trying to fix the same issue and my scenario was similar. I was trying to render a youtube Video on my page and on top of the video i wanted to place some div with some information.

But the youtube video being contained into an iframe wasn't letting me do that. Irrespective of the
z-index that i gave to the elements.

Then this post helped - https://stackoverflow.com/a/9074366/1484384

Basically its about the wmode. Check the above post to see how to work with it.

Here is some code from that post:

<iframe title="YouTube video player" width="480" height="390 src="http://www.youtube.com/embed/lzQgAR_J1PI?wmode=transparent">

Or

//Fix z-index youtube video embedding

$(document).ready(function (){
  $('iframe').each(function(){
    var url = $(this).attr("src");
    $(this).attr("src",url+"?wmode=transparent");
  });
});
Community
  • 1
  • 1
Vishnu Narang
  • 605
  • 8
  • 15
0

For those who are using jQueryUI, I came up with the following solution.

Add the following function and call it from the open event of your dialogs. If your browser is IE it will insert an iFrame into the Modal overlay or else add it to the dialog background.

// Simple IE Detection.
var isIE = Object.hasOwnProperty.call(window, "ActiveXObject");

// Fix IE bug where an iFrame from below will cover a dialogs contents.
function dialogIFrameFix(event /* object */) {
    setTimeout(function () {
        if (event && event.target && isIE) {
            var $dialog = $(event.target.parentElement);
            // Get the modal overlay if found.
            var $fixTarget = $dialog.next('.ui-widget-overlay');
            // Use the dialog body if there is no overlay.
            if (!$fixTarget || !$fixTarget.length)
                $fixTarget = $dialog;
            // Add as first child so it is covered by all of the other elements
            $fixTarget.prepend('<iframe class="iFrameFix" src="about:blank" style="position:absolute;top:0;left:0;width:100%;height:100%"></iframe>');
        }
    }, 10);
}

You would then call it as follows..

.dialog({
    open: function (event, ui) {
        dialogIFrameFix(event);
    }
});
AnthonyVO
  • 3,821
  • 1
  • 36
  • 41