How to get an IFrame to be responsive in iOS Safari?

HtmlCssIframe

Html Problem Overview


The problem is that when you have to use IFrames to insert content into a website, then in the modern web-world it is expected that the IFrame would be responsive as well. In theory it's simple, simply aider use <iframe width="100%"></iframe> or set the CSS width to iframe { width: 100%; } however in practice it's not quite that simple, but it can be.

If the iframe content is fully responsive and can resize itself without internal scroll bars, then iOS Safari will resize the iframe without any real issues.

If you consider the following code:

<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=9,10,11" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Iframe Isolation Test</title>
    
	<style type="text/css" rel="stylesheet">
	
		#Main {
			padding: 10px;
		}
	</style>
</head>
<body>
	<h1>Iframe Isolation Test 13.17</h1>
	<div id="Main">
		<iframe height="950" width="100%" src="Content.html"></iframe>
	</div>
</body>
</html>

With the Content.html:

<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=9,10,11" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Iframe Isolation Test - Content</title>

	<style type="text/css" rel="stylesheet">
				
		#Main {
			width: 100%;
			background: #ccc;
		}

	</style>
</head>
<body>
	<div id="Main">
		<div id="ScrolledArea">
			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc malesuada purus quis commodo convallis. Fusce consectetur mauris eget purus tristique blandit. Nam nec volutpat augue. Aliquam sit amet augue vitae orci fermentum tempor sit amet gravida augue. Pellentesque convallis velit eu malesuada malesuada. Aliquam erat volutpat. Nam sollicitudin nulla nec neque viverra, non suscipit purus tincidunt. Aenean blandit nisi felis, sit amet ornare mi vestibulum ac. Praesent ultrices varius arcu quis fringilla. In vitae dui consequat, rutrum sapien ut, aliquam metus. Proin sit amet porta velit, suscipit dignissim arcu. Cras bibendum tellus eu facilisis sodales. Vestibulum posuere, magna ut iaculis consequat, tortor erat vulputate diam, ut pharetra sapien massa ut magna. Donec massa purus, pharetra sed pellentesque nec, posuere ut velit. Nam venenatis feugiat odio quis tristique. 
		</div>		
	</div>
</body>
</html>

Then this works without issues in iOS 7.1 Safari. You can change between landscape and portrait without any issues.

enter image description here enter image description here

However by simply changing the Content.html CSS by adding this:

	#ScrolledArea {
		width: 100%;
		overflow: scroll;
		white-space: nowrap;
		background: #ff0000;
	}

You get this:

enter image description here enter image description here

As you can see, even though the Content.html content is fully responsive (div#ScrolledArea has overflow: scroll set) and the iframe width is 100% the iframe still takes the full width of the div#ScrolledArea as if the overflow does not even exist. Demo

In cases like this, were the iframecontent has scrolling areas on it, the question becomes, how to get the iframe responsive, when the iframe content has horizontally scrolling areas? The problem here is not in the fact that the Content.html is not responsive, but in the fact that the iOS Safari simply resizes the iframe so that the div#ScrolledArea would be fully visible.

Html Solutions


Solution 1 - Html

The solution for this problem is actually quite simple and there are two ways to go about it. If you have control over the Content.html then simply change the div#ScrolledArea width CSS to:

width: 1px;
min-width: 100%;
*width: 100%;
	

Basically the idea here is simple, you set the width to something that is smaller than the viewport (iframe width in this case) and then overwrite it with min-width: 100% to allow for actual width: 100% which iOS Safari by default overwrites. The *width: 100%; is there so the code would remain IE6 compatible, but if you do not care for IE6 you can omit it. Demo

enter image description here enter image description here

As you can see now, the div#ScrolledArea width is actually 100% and the overflow: scroll; can do it's thing and hide the overflowing content. If you have access to the iframe content, then this is preferable.

However if you do not have access to the iframe content (for what ever reason) then you can actually use the same technique on the iframe itself. Simply use the same CSS on the iframe:

iframe {
    width: 1px;
	min-width: 100%;
	*width: 100%;
}

However, there is one limitation with this, you need to turn off the scrollbars with scrolling="no" on the iframe for this to work:

<iframe height="950" width="100%" scrolling="no" src="Content.html"></iframe>

If the scrollbars are allowed, then this wont work on the iframe anymore. That said, if you modify the Content.html instead then you can retain the scrolling in the iframe. Demo

Solution 2 - Html

The problem, it seems, is that Mobile Safari will refuse to obey the width of your iFrame if the document it contains is wider than what you have specified. Example:

http://jsbin.com/hapituto/1

On a desktop browser, you will see an iFrame and a Div both set to 300px. The contents is wider so you can scroll the iFrame.

On mobile safari, however, you will notice that the iFrame is auto-expanded to the width of the content.

My guess is that this is a workaround for long-standing issues with scrolling content within a page. In the past, if you had a large scrolling iframe on a touch device, you'd get 'stuck' in the iframe as that would be scrolling instead of the page itself. It appears Apple has decided that the default behavior of an iFrame is 'no scroll' and expands to prevent it.

One option may be this workaround. Instead of assuming the iFrame will scroll, place the iframe in a DIV that you do have control over and let that scroll.

example: http://jsbin.com/zakedaja/1

Example markup:

<div style="overflow: scroll; -webkit-overflow-scrolling: touch; width: 300px;">
   <iframe src="http://jsbin.com/roredora/1/" style="width: 600px;"></iframe>
</div>

On mobile safari, you can now scroll the contents of the now fully-expanded iFrame via the div that is containing it.

The catch: This looks really ugly on a desktop browser, as now you have double scrollbars. So you may have to do some browser detection with JS to get around this.

Solution 3 - Html

I needed a cross-browser solution. Requirements were:

  • needed to work on both iOS and elsewhere
  • don't have access to the content in the iFrame
  • need it to scroll!

Building off what I learned from @Idra regarding scrolling="no" on iOS and this post about fitting iFrame content to the screen in iOS here's what I ended up with. Hope it helps someone =)

HTML

<div id="url-wrapper"></div>

CSS

html, body{
	height: 100%;
}

#url-wrapper{
	margin-top: 51px;
	height: 100%;
}

#url-wrapper iframe{
	height: 100%;
    width: 100%;
}

#url-wrapper.ios{
	overflow-y: auto;
	-webkit-overflow-scrolling:touch !important;
	height: 100%;
}

#url-wrapper.ios iframe{
	height: 100%;
    min-width: 100%;
    width: 100px;
    *width: 100%;
}

JS

function create_iframe(url){

	var wrapper = jQuery('#url-wrapper');

	if(navigator.userAgent.match(/(iPod|iPhone|iPad)/)){
		wrapper.addClass('ios');
		var scrolling = 'no';
	}else{
		var scrolling = 'yes';
	}

	jQuery('<iframe>', {
		src: url,
		id:  'url',
		frameborder: 0,
		scrolling: scrolling
	}).appendTo(wrapper);

}

Solution 4 - Html

The problem with all these solutions is that the height of the iframe never really changes.

This means you won't be able to center elements inside the iframe using Javascript, position:fixed;, or position:absolute; since the iframe itself never scrolls.

My solution detailed here is to wrap all the content of the iframe inside a div using this CSS:

#wrap {
	position: fixed;
	top: 0;
	right:0;
	bottom:0;
	left: 0;
	overflow-y: scroll;
  	-webkit-overflow-scrolling: touch;
}

This way Safari believes the content has no height and lets you assign the height of the iframe properly. This also allows you to position elements in any way you wish.

You can see a quick and dirty demo here.

Solution 5 - Html

This issue is also present on iOS Chrome.

I glanced through all the solutions above, most are very hacky.

If you don't need support for older browsers, just set the iframe width to 100vw;

iframe {
  max-width: 100%; /* Limits width to 100% of container */
  width: 100vw; /* Sets width to 100% of the viewport width while respecting the max-width above */
}

Note : Check support for viewport units https://caniuse.com/#feat=viewport-units

Solution 6 - Html

I am working with ionic2 and system config is as below-


******************************************************

Your system information:

Cordova CLI: 6.4.0 
Ionic Framework Version: 2.0.0-beta.10
Ionic CLI Version: 2.1.8
Ionic App Lib Version: 2.1.4
ios-deploy version: Not installed
ios-sim version: 5.0.8 
OS: OS X Yosemite
Node Version: v6.2.2
Xcode version: Xcode 7.2 Build version 7C68



******************************************************

For me this issue got resolved with this code-
for html iframe tag-

<div class="iframe_container">
      <iframe class= "animated fadeInUp" id="iframe1" [src]='page' frameborder="0" >
        <!--  <img src="img/video-icon.png"> -->
      </iframe><br>
   </div>

See css of the same as-


.iframe_container {
  overflow: auto; 
  position: relative; 
  -webkit-overflow-scrolling: touch;
  height: 75%;
}

iframe {
  position:relative;
  top: 2%;
  left: 5%;
  border: 0 !important;
  width: 90%;
}

Position property play a vital role here in my case.
position:relative;

It may help you too!!!

Solution 7 - Html

I had an issue with width on the content pane creating a horizontal scroll bar for the iframe. It turned out that an image was holding the width wider than expected. I was able to solve it by setting the all of the images css max-width to a percent.

<meta name="viewport" content="width=device-width, initial-scale=1" />

img {
        max-width: 100%;
        height:auto;
    }

Solution 8 - Html

CSS only solution

HTML

<div class="container">
    <div class="h_iframe">
        <iframe  src="//www.youtube.com/embed/9KunP3sZyI0" frameborder="0" allowfullscreen></iframe>
    </div>
</div>

CSS

html,body {
    height:100%;
}
.h_iframe iframe {
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
}

DEMO

Another demo here with HTML page in iframe

Solution 9 - Html

in fact for me just worked in ios disabling the scroll

<iframe src="//www.youraddress.com/" scrolling="no"></iframe>

and treating the OS via script.

Solution 10 - Html

For me CSS solutions didn't work. But setting the width programmatically does the job. On iframe load set the width programmatically:

 $('iframe').width('100%');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIdraView Question on Stackoverflow
Solution 1 - HtmlIdraView Answer on Stackoverflow
Solution 2 - HtmlDA.View Answer on Stackoverflow
Solution 3 - HtmlgerbzView Answer on Stackoverflow
Solution 4 - HtmlPierView Answer on Stackoverflow
Solution 5 - HtmlPrathamesh GharatView Answer on Stackoverflow
Solution 6 - HtmlS.YadavView Answer on Stackoverflow
Solution 7 - HtmlDr. Aaron DishnoView Answer on Stackoverflow
Solution 8 - Html4dgauravView Answer on Stackoverflow
Solution 9 - HtmlLuiz RossiView Answer on Stackoverflow
Solution 10 - HtmlUmer QureshiView Answer on Stackoverflow