Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IFrame scrollbar disappears on chrome when visibility changes

Is Google Chrome on Windows having problems to render iframe scrollbars?

I wrote a very simple code to show what is happening (at least with me on chrome 52.0.2743.82 m):

  <button>Toggle visibility</button>
  <br />
  <iframe scrolling="yes" seamless src="https://en.wikipedia.org/wiki/Lorem_ipsum" frameborder="0" style="width: 700px; height: 300px"></iframe>

  <script type="text/javascript">
    $("button").on("click", function() {
      $("iframe").toggle();
    });
  </script>

Plunker link to code

When the page is loaded, the iframe as it scrollbar are visible.

Hide and show the iframe clicking the button. The scrollbar disappears.

This issue apparently occurs only in chrome.

Anyone is experiencing this too? Any fixes/workarounds?

like image 235
Alexandre Perez Avatar asked Jul 24 '16 23:07

Alexandre Perez


People also ask

How do I stop the scroll bar from disappearing in Chrome?

Open a Chrome window. In the address bar, enter "chrome://flags," and navigate to that page. Scroll down to Overlay Scrollbars, and set the field to "Disabled."

Why does my scroll bar keep disappearing in Chrome?

Remove Extensions Enabled extensions can also cause the Chrome vertical scroll bar missing problem. You can disable all extensions and then reboot Chrome. If the vertical scroll bar is back, the vertical scroll bar disappears because of one or some extensions.

How do I fix my disappearing scroll bar?

Go to Settings / Ease of Access / Display and turn off Automatically hide scroll bars in Windows.


3 Answers

It seems that bug appeared with the update Chrome 52.0.2743.82 (http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html)

One possible workaround is to use the attribute visibility with position: absolute instead of display to show or hide the iframe.

A chrome bug ticket exists for this item: https://bugs.chromium.org/p/chromium/issues/detail?id=641881

like image 188
lepix Avatar answered Oct 04 '22 00:10

lepix


I've had this problem, and using visibility instead of display: none wasn't an option.

My workaround was to set overflow: scroll on the <body> of the document being displayed in the iframe, whenever I set the iframe to be visible again. This seems to force the scrollbar to appear on the iframe again. You can then reset the overflow to its old value, and the scrollbar will remain on the iframe. You need to wait for a repaint before you can reset the overflow, though, so I put this in a timeout with delay 0.

function showIframe(iframe) {
    var iframeBody = iframe.contentDocument.body;
    $(iframe).show();
    var oldOverflow = iframeBody.css("overflow");
    iframeBody.css("overflow", "scroll");
    window.setTimeout(function () {
        iframeBody.css("overflow", oldOverflow);
    }, 0);
}

There is a "flash" of scrollbar with this workaround if the iframe in question doesn't need to scroll, though, so it might be worth using the visibility workaround for that brief moment where the repaint is required, to avoid the flash.

like image 38
Joseph O'Donnell Avatar answered Oct 04 '22 00:10

Joseph O'Donnell


Here's a workaround I've developed for an application I'm building. It has multiple <iframe> elements in a Foundation tab-control.

I used MutationObserver to observe when the <iframe>'s parent element (a Foundation div.tabs-content div.content element) becomes active, then I toggle the iframe's document's overflow property. The runtime effect is imperceivable.

I originally wanted to observe the <iframe> directly, however no DOM mutation events were raised when the iframe itself's changed display property, I guess because technically speaking element.style values are not part of the DOM-structure proper.

Here's my code (Vanilla.js, no jQuery). If you're using in your application you will want to replace my visibility-detection code with something that is applicable to your document:

window.addEventListener('DOMContentLoaded', function(e) {

    var observer = new MutationObserver( onContentMutated );
    var options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['class'] };

    var iframeContainers = document.querySelectorAll('.tabs-content .content');
    for(var i = 0; i < iframeContainers.length; i++) {

        observer.observe( iframeContainers[i], options );
    }
});

function onContentMutated(mutations) {

    for(var i = 0; i < mutations.length; i++) {
        var m = mutations[i];

        var thisIsNowAnActiveTab = m.target.classList.contains('active');
        if( thisIsNowAnActiveTab ) {
            // get the corresponding iframe and fiddle with its DOM

            var iframes = m.target.getElementsByTagName("iframe");
            if( iframes.length == 0 ) continue;
            var iframe = iframes[0];

            iframe.contentWindow.document.documentElement.style.overflow = 'hidden';

            // the timeout is to trigger Chrome to recompute the necessity of the scrollbars, which makes them visible again. Because the timeout period is 0 there should be no visible change to users.
            setTimeout( function(s) {

                s.overflow = 'auto';

            }, 0, iframe.contentWindow.document.documentElement.style );
        }

        console.log( m.type );
    }
}
like image 40
Dai Avatar answered Oct 03 '22 22:10

Dai