Skip to content

Instantly share code, notes, and snippets.

@KrzysztofPrzygoda
Last active May 17, 2021 04:24
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KrzysztofPrzygoda/418d05679ec83a3df7609bf7e36f6465 to your computer and use it in GitHub Desktop.
Save KrzysztofPrzygoda/418d05679ec83a3df7609bf7e36f6465 to your computer and use it in GitHub Desktop.
Workaround to iOS WebKit iframe bugs (including Bootstrap Popover) // source https://jsbin.com/mevurem
/*
Embracing iOS WebKit weirdness with iframes
**iOS WebKit iframe bug description**:
https://bugs.webkit.org/show_bug.cgi?id=155198
**My current findings**:
1. iOS WebKit resizes iframes to the full size of their content - it's a bug known since 2016 and still not resolved in iOS 11.
2. To fit iframe contents, its div container must have w/h defined in pixels - any relative measures (like %, vw/vh) doesn't work.
3. Some RWD pages (let's say with "incomplete RWD") are experiencing iframe overflow (iframe does not fit into the iframe-container).
Unfortunately, we can't fix that from the iframe outside and to solve this issue, document inside iframe requires at least:
body {
max-width: 100vw !important;
}
Optionally, we can scale iframe content as a last resort.
4. Because of 2, to keep container proportion we need to use at least CSS media queries or JS to adjust its height.
**Some incomplete solutions**:
- https://github.com/ampproject/amphtml/issues/11133
- https://www.spacevatican.org/2015/4/7/on-mobile-safari-and-iframes/
- https://stackoverflow.com/questions/23060281/external-html-file-in-bootstrap-popover-content
- https://stackoverflow.com/questions/23083462/how-to-get-an-iframe-to-be-responsive-in-ios-safari
- https://stackoverflow.com/questions/24157940/iframe-height-auto-css
- https://stackoverflow.com/questions/9975810/make-iframe-automatically-adjust-height-according-to-the-contents-without-using
- https://stackoverflow.com/questions/26046373/iframe-scrolling-ios-8
- https://stackoverflow.com/questions/26738764/ios8-safari-webkit-overflow-scrolling-touch-issue/26743685#26743685
*/
/* 1. Beautifiers (optional) */
iframe {
border: none;
width: 100%;
height: 100%;
}
.simple-container {
width: 50vw;
height: 50vh;
padding: 1em;
}
/* 2. Resolving iOS iframe rendering issue */
/* 2.1. Sizing reorganization (obligatory) */
.popover {
/* To control popover size by .popover-body instead of .popover */
max-width: 100% !important;
}
.popover-body {
box-sizing: border-box;
max-width: 100%;
max-height: 100%;
}
.iframe-container,
.iframe-container iframe {
width: 100%;
height: 100%;
margin: 0 !important;
padding: 0 !important;
box-sizing: border-box;
}
.fixed iframe {
/* This only fits iframe inside iframe-container but prevents scrolling */
width: 0;
height: 0;
min-width: 100%;
min-height: 100%;
}
.popover-body {
width: 640px; height: 360px;
}
/* 2.2. RWD Resizings (optional) */
@media only screen and (max-width: 568px)
{
.rwd .popover-body {
width: 320px; height: 180px;
}
}
@media only screen and (min-width: 569px) and (max-width: 965px)
{
.rwd .popover-body {
width: 480px; height: 270px;
}
}
@media only screen and (min-width: 968px) and (max-width: 1023px)
{
.rwd .popover-body {
width: 640px; height: 360px;
}
}
/* 2.3. Resolving iOS iframe scrolling issue (obligatory) */
/*
Due to iOS WebKit bug an iframe content cannot be scrolled, because WebKit renders entire iframe content:
https://bugs.webkit.org/show_bug.cgi?id=155198
(still not resolved on iOS11)
The workaround is to scroll an div container content with full iframe rendered inside.
*/
.scroll {
overflow: scroll !important;
-webkit-overflow-scrolling: touch !important;
}
/* 2.4. Resolving iframe and container double scrollbars on desktop browsers (rather obligatory) */
.no-scrollbar {
position: relative;
}
.no-scrollbar iframe {
position: absolute;
top: 0;
left: 0;
}
.no-scrollbar {
/* Hide scrollbars in IE Edge */
/* Autohiding is needed inside iframe document */
/*-ms-overflow-style: -ms-autohiding-scrollbar;*/
/* In the parent iframe container we don't want any scrollbars */
-ms-overflow-style: none;
}
/* 3. Scale non-RWD iframe content (optional) */
/* Warning! iOS 11 Safari crashes on two-fingers zoom of a page with scaled iframe */
.scale {
-ms-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-o-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
.scale.x2 {
width: 200% !important;
height: 200% !important;
-ms-transform: scale(0.5);
-moz-transform: scale(0.5);
-o-transform: scale(0.5);
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
.scale.x4 {
width: 400% !important;
height: 400% !important;
-ms-transform: scale(0.25);
-moz-transform: scale(0.25);
-o-transform: scale(0.25);
-webkit-transform: scale(0.25);
transform: scale(0.25);
}
/* DEBUG */
/* To receive click events on iOS */
/*
* {
cursor: pointer;
}
*/
.popover-body {
border: 1px green dotted;
}
.simple-container,
.iframe-container {
border: 1px blue dotted;
}
iframe {
border: 1px red dotted;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>iOS iframes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="cache-control" content="no-cache" />
<!-- Solution -->
<link rel="stylesheet" href="iframe.css" />
<!-- Bootstrap with Popover -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.bundle.min.js"></script>
<script>
jQuery(function ($) {
$('a.popover-me').on('click', function(e) {
e.preventDefault();
if (!$(this).data('bs.popover')) $(this).popover({
container: 'body',
boundary: 'window',
placement: 'auto',
trigger: 'manual',
html: true,
title: $(this).text(),
content: '<div class="iframe-container scroll no-scrollbar"><iframe src="' + this.href + '"></iframe></div>'
});
$(this).popover('toggle');
});
});
</script>
</head>
<body class="rwd" style="padding: 2em;">
<h2>Embracing iOS WebKit weirdness with iframes</h2>
<div class="alert alert-primary" role="alert">
Ready for Bootstrap v4.0.0 <a class="popover-me" href="https://en.wikipedia.org/wiki/WebKit">Popover</a>.
</div>
<div class="alert alert-danger" role="alert">
Display this page on iOS device.
</div>
<h3>1. Workaround for scrollable iframe</h3>
<p>
<div class="popover-body">
<div class="iframe-container scroll no-scrollbar">
<iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
</div>
</div>
</p>
<div class="alert alert-warning" role="alert">
<strong>Hint: </strong>
<em>
Some RWD pages (let's say with "incomplete RWD") are experiencing iframe overflow (iframe does not fit into the iframe-container).
Unfortunately, we can't fix that from the iframe outside and to solve this issue, document inside iframe requires at least:
</em>
<br /><br />
<pre>
body {
/* Resolves iOS overflow rendering bug */
max-width: 100vw !important;
}
</pre>
<em>
Optionally, you can scale iframe document as below.
</em>
</div>
<h3>2. Workaround for non-RWD scrollable iframe</h3>
<em>
Page inside iframe is zoomed out to 50%.
</em>
<p>
<div class="popover-body">
<div class="iframe-container scroll no-scrollbar scale x2">
<iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
</div>
</div>
</p>
<h3>3. Workaround for fixed iframe</h3>
<em>
iframe fits in iframe-container.
</em>
<p>
<div class="popover-body">
<div class="iframe-container fixed scroll no-scrollbar">
<iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
</div>
</div>
</p>
<h3>4. [BUG] Plain iframe inside simple container</h3>
<em>
iframe should fit into simple container.
</em>
<p>
<div class="simple-container">
<iframe src="https://en.wikipedia.org/wiki/WebKit"></iframe>
</div>
</p>
</body>
</html>
@zoltiecodes
Copy link

Hi. Thank you for your solution, it's working for me however there's an issue with absolute and fixed position inside the iframe content.

This is the solution that worked for me completely: https://github.com/PierBover/ios-iframe-fix but this only works if you can access and modify the content in the iframe. This way you don't need to wrap the iframe tag, just modify the iframe content as described.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment