iOS 11 WebKit iframe错误的解决方法

时间:2018-04-10 08:58:25

标签: iframe mobile-webkit

iOS WebKit iframe错误说明

iOS WebKit将iframe调整为其内容的完整大小(参见下图)。这是一个自2016年以来已知的错误,但仍未在iOS 11中解决:https://bugs.webkit.org/show_bug.cgi?id=155198

iOS 11

我目前的调查结果

1。对于固定的iframe内容(例如视频)

下面应用CSS就足够了,但它可以防止iframe内容滚动。

.fixed iframe {
    width: 0;
    height: 0;

    min-width: 100%;
    min-height: 100%;    
}

2。对于可滚动的iframe内容(例如页面)

  1. 我们需要两个iframe容器:一个作为边界(固定大小),第二个作为滚动区域。
  2. 要适合iframe内容,其div容器必须以像素为单位定义w / h。任何相关度量(如%,vw / vh)都不起作用。
  3. 有些RWD页面(假设“不完整的RWD”)正在遇到iframe溢出(iframe不适合iframe容器)。 不幸的是,我们无法从iframe中解决这个问题并解决此问题,iframe中的文档至少需要:

    body {
        max-width: 100vw !important;
    }
    

    我们可以选择扩展iframe内容作为最后的手段。

  4. 由于2,为了保持容器比例,我们至少需要使用CSS媒体查询或JS来调整其高度。

  5. 一些不完整的解决方案

    我的解决方法已发布在答案中。

1 个答案:

答案 0 :(得分:10)

这就是我到目前为止所做的。任何贡献都非常赞赏。 Github Gist上的最新版本。

/* 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>