IFrame scrollbar disappears on chrome when visibility changes

Does Google Chrome on Windows have problems displaying iframe scroll lists?

I wrote 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 Code Link

When the page is loaded, the iframe is displayed as a scroll bar.

Hide and show the iframe by clicking the button. The scroll bar disappears.

This problem, apparently, occurs only in chrome.

Does anyone experience this too? Any fixes / workarounds?

+7
javascript html google-chrome iframe scrollbar
source share
8 answers

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

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

There is a chrome big code for this item: https://bugs.chromium.org/p/chromium/issues/detail?id=641881

+4
source share

I had this problem and using visibility instead of display: none not possible.

My workaround was to set overflow: scroll to the <body> document displayed in the iframe, whenever I set the iframe again. This seems to make the scrollbar appear again on the iframe. You can then reset overflow to its old value, and the scrollbar will remain on the iframe. You need to wait for the redraw before you can reset overflow , however, so I put this in a timeout with a delay of 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” scroll bar in this workaround if you don't need to scroll the iframe, so you might want to use the visibility workaround for this brief moment when you need to redraw to avoid the flash.

+3
source share

Here is a workaround that I developed for the application that I am creating. It has several <iframe> elements in the Foundation tab control.

I used MutationObserver to observe when the parent <iframe> element (Foundation element div.tabs-content div.content ) becomes active , then I switch the iframe property of document overflow . Runtime effect is not possible.

I initially wanted to observe <iframe> directly, but no DOM mutation events were raised when the iframe itself changed the display property, I think, because technically speaking element.style values element.style not part of the DOM structure itself.

Here is my code (Vanilla.js, no jQuery). If you use in your application, you will want to replace my visibility detection code with something that applies 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 ); } } 
+1
source share

In this example, you can:
$("iframe").toggle(1)

In my case, it worked by setting the height:
$("iframe").css("height", "100%")

+1
source share

I had a similar issue in Chrome with an iframe embedded in the jQuery UI tab. When the first tab containing the iframe is displayed, a scroll bar appears. But when I switch to another tab and back to the tab with iframe, then the scrollbar disappears. All the solutions offered here did not help me. Here is what I did to solve the problem: First, I create tabs:

 $("#mytabs").tabs(); 

Then I bind the function to the tabsactivate event, and I check to see if the targeting contains the iframe. If so, I call the fixChromeScrollBar () function, described below:

 $("#mytabs").on("tabsactivate", function(event, ui) { if ($(event.originalEvent.target).attr("href") == "#mytab-with-iframe") { fixChromeScrollBar(); } }); 

And finally, here is the fixChromeScrollBar () function, which sets the iframe body overflow style attribute (as already mentioned) to either "scroll" or "automatically." I noticed that when I define only “auto” or “scroll”, then if I switch to another tab and return to the iframe, I will lose the scroll bar. The only way to support them is to alternate the two values ​​each time an iframe appears. This is strange, but it works:

 function fixChromeScrollBar() { var iFrameBody = $("#myiframe").contents().find("body"); var originalOverflow = $(iFrameBody).css("overflow"); if (originalOverflow == "visible" || originalOverflow == "auto") { $(iFrameBody).css("overflow", "scroll"); } else { $(iFrameBody).css("overflow", "auto"); } } 

You may notice that this method is only called when you switch to the tab containing the iframe, so if you click several times on this tab without switching to another, this code will be executed only for the first time.

0
source share

Apparently, installing src updates the iframe in chrome, for this example code would be:

 <script type="text/javascript"> $("button").on("click", function() { $('iframe').toggle().attr('src', function(i, val) { return val; }); }); </script> 
0
source share

I adapted the Dai example to my own React IFrame component. I have an iframe inside the tab bar, which itself is in the precast panel. When one of them switches, I force the iframe to redraw. It works great.

 private iframe: HTMLIFrameElement; private displayObserver: MutationObserver; componentDidMount() { // Detect style attribute changes for the containing collapsible components // If the display goes from 'none' to something else, then we need to redraw the iframe // so we get the scrollbar back as it should be. if (isChrome()) { this.displayObserver = new MutationObserver(this.onContentMutated); const options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['style'] }; const tabPanelAncestor = this.findAncestor(this.iframe, '.tab-panel-content'); if (tabPanelAncestor) { this.displayObserver.observe(tabPanelAncestor, options); } const collapsibleAncestor = this.findAncestor(this.iframe, '.collapsible'); if (collapsibleAncestor) { this.displayObserver.observe(collapsibleAncestor, options); } } } private readonly onContentMutated = (mutations: Array<MutationRecord>) => { R.forEach( (mutation) => { const targetElement = mutation.target as Element; const style = targetElement.getAttribute('style'); if (style && !style.match(/display: none/)) { this.iframe.contentWindow.location.reload(true); } }, mutations); } private readonly findAncestor = (element: HTMLElement, sel: string): Node | null => { if (typeof element.closest === 'function') { return element.closest(sel) || null; } let ancestor: HTMLElement | null = element; while (ancestor) { if (ancestor.matches(sel)) { return ancestor; } ancestor = ancestor.parentElement; } return null; } 
0
source share

Add

 iframe { overflow-y: scroll; } 

to your CSS

-2
source share

All Articles