Как заставить IFrame быть отзывчивым в iOS Safari?

134

Проблема в том, что когда вам нужно использовать IFrame для вставки контента на веб-сайт, то в современном веб-мире ожидается, что IFrame также будет отзывчивым. Теоретически это просто, просто помощник использует <iframe width="100%"></iframe>или устанавливает ширину CSS, iframe { width: 100%; }однако на практике это не так просто, но может быть.

Если iframeсодержимое полностью адаптивно и может изменять свой размер без внутренних полос прокрутки, то iOS Safari изменит размер iframeбез каких-либо реальных проблем.

Если вы рассмотрите следующий код:

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

С 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>

Тогда это работает без проблем в iOS 7.1 Safari. Вы можете без проблем переключаться между альбомной и портретной ориентацией.

введите описание изображения здесь введите описание изображения здесь

Однако, просто изменив Content.html CSS, добавив это:

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

Вы получаете это:

введите описание изображения здесь введите описание изображения здесь

Как вы можете видеть, даже несмотря на то, content.html содержимого полностью реагирует ( Div # ScrolledArea имеет overflow: scrollмножество) и IFRAME ширина 100% , то IFrame все еще занимает всю ширину сНа # ScrolledArea как будто переполнение даже не существует. демонстрация

В таких случаях, когда у iframeконтента есть области прокрутки, возникает вопрос, как получить iframeотзывчивость, когда у содержимого iframe есть области горизонтальной прокрутки? Проблема здесь не в том, что Content.html не реагирует, а в том, что iOS Safari просто изменяет размер iframe, чтобы div#ScrolledAreaон был полностью виден.

Идра
источник
Вы можете поделиться с нами ссылкой? Вы хотите сказать, что iOS расширит iFrame на всю ширину страницы внутри, если внутри страницы есть контент со white-space: nowrapстилем?
Д.А.
@DA Я добавил демонстрации и к проблеме, и к решению. И нет, white-space: nowrapпроблема не в этом. Я просто использую его, чтобы получить максимальную ширину div#ScrolledArea. Проблема возникает, когда в содержимом IFrame есть области с горизонтальной прокруткой. Если это так, iOS Safari просто игнорирует ваши настройки ширины и показывает содержимое дыр и нарушает отзывчивость сайта.
Идра
Хм ... Интересно, это «особенность». Было бы неудобно иметь прокручиваемую область (iFrame), которая содержит прокручиваемый контент. Было бы очень сложно взаимодействовать с сенсорным экраном.
DA.
@DA Конечно, это случай племянницы, и то, что вы сказали, может быть правдой (зависит от реализации, работает для нас), и большинство сайтов не имеют горизонтально прокручиваемых областей, но когда вы делаете ... вы даже не можете себе представить сколько времени я потратил на это. Но это может быть проблемой, даже если у вас есть изображения, которые скрыты и прокручиваются кнопками или что-то в этом роде.
Идра
Похоже, есть связанные вопросы по этому поводу: stackoverflow.com/questions/5267996/… Это действительно похоже на «особенность» мобильного сафари ... он пытается гарантировать, что размер содержимого изменяется таким образом, чтобы пользователь мог все еще взаимодействовать с ним. Я не уверен, что произойдет, если у вас есть прокручиваемый контент в прокручиваемом iframe ... как Safari интерпретирует прокрутку во вложенных элементах прокрутки?
Д.А.

Ответы:

289

Решение этой проблемы на самом деле довольно простое, и есть два способа решить эту проблему. Если у вас есть контроль над Content.html, просто измените div#ScrolledAreaширину CSS на:

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

По сути, идея здесь проста: вы устанавливаете значение width, которое меньше, чем область просмотра (в этом случае ширина iframe), а затем перезаписываете его, min-width: 100%чтобы учесть фактическое, width: 100%какое iOS Safari по умолчанию перезаписывает. Он *width: 100%;существует, чтобы код оставался совместимым с IE6, но если вам не нужен IE6, вы можете его опустить. демонстрация

введите описание изображения здесь введите описание изображения здесь

Как вы теперь можете видеть, div#ScrolledAreaширина на самом деле составляет 100%, и он overflow: scroll;может сделать это и скрыть переполненный контент. Если у вас есть доступ к содержимому iframe, это предпочтительнее.

Однако, если у вас нет доступа к содержимому iframe (по какой-либо причине), вы можете использовать тот же метод для самого iframe. Просто используйте тот же CSS в iframe:

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

Однако здесь есть одно ограничение: вам нужно отключить полосы прокрутки с scrolling="no"помощью iframe, чтобы это работало:

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

Если полосы прокрутки разрешены, то это больше не будет работать в iframe. Тем не менее, если вместо этого вы измените Content.html, вы можете сохранить прокрутку в iframe. демонстрация

Идра
источник
1
Как @NickGottlieb упоминалось, я должен был добавить !importantк widthатрибуту , чтобы получить IFrame отзывчивым-веб-дизайн готов на iPhone 4 с прошивкой 7
malisokan
@ ЮнгвиртТони Не требуется, чтобы обходной путь работал, возможно, что widthбыло установлено ранее с !importantили более высокий приоритет CSS перезаписал его. В единичных случаях в iPhone 4 iOS7 она не понадобилась.
Idra
Мне тоже не нужно было! Важно. Отлично работает и на iOS 8. Ура
Сэм Поттс
Мне нужна прокрутка = нет только при необходимости, в противном случае прокрутка = да. Так что я должен обнаружить? Это проблема iOS? или проблема с webkit? или...?
gerbz
@ggwarpig - это проблема iOS, когда iOS Safari автоматически включает атрибут seamless, и вы не можете перезаписать его. Если у вас есть контроль над содержимым, вам необходимо изменить содержимое, чтобы в scrolling="yes"противном случае это было невозможно исправить, чтобы исправление работало в IFRAME, вам нужно иметь scrolling="no"только IFRAME
Идра,
24

Проблема, похоже, в том, что Mobile Safari откажется подчиняться ширине вашего iFrame, если документ, который он содержит, шире, чем вы указали. Пример:

http://jsbin.com/hapituto/1

В браузере настольного компьютера вы увидите, что для iFrame и Div установлено значение 300 пикселей. Содержимое шире, поэтому вы можете прокручивать iFrame.

Однако в мобильном сафари вы заметите, что iFrame автоматически расширяется до ширины содержимого.

Я предполагаю, что это способ решения давних проблем с прокруткой контента на странице. В прошлом, если у вас был большой прокручиваемый iframe на сенсорном устройстве, вы бы «застряли» в iframe, поскольку это была бы прокрутка вместо самой страницы. Похоже, Apple решила, что поведение iFrame по умолчанию - «без прокрутки», и расширяет его, чтобы предотвратить это.

Одним из вариантов может быть этот обходной путь. Вместо того, чтобы предполагать, что iFrame будет прокручиваться, поместите iframe в DIV, который у вас есть, и позвольте ему прокручиваться.

пример: http://jsbin.com/zakedaja/1

Пример разметки:

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

В мобильном сафари теперь можно прокручивать содержимое теперь полностью развернутого iFrame с помощью содержащего его div.

Уловка: в браузере для настольных ПК это выглядит ужасно, так как теперь у вас есть двойные полосы прокрутки. Поэтому вам, возможно, придется выполнить обнаружение браузера с помощью JS, чтобы обойти это.

DA.
источник
1
Я бы по-прежнему утверждал, что это не входит в объем вопроса, потому что решение, которое вы здесь показали, является стандартным способом имитации прокрутки iframe отверстия в iOS Safari, но, принимая во внимание эту проблему iOS, является проблемой прокрутки IFrame (контент или иначе), то приятно иметь его здесь.
Идра
1
Я думаю, я не до конца понимаю ваш вопрос. Насколько я понимаю, проблема заключается в том, что в iOS Mobile Safari в первую очередь пытается предотвратить прокрутку iFrame и устанавливает ширину на нем. Я неправильно понимаю вашу проблему?
Д.А.
По сути, в этом проблема, просто необходимое ее решение другое. В исходной проблеме содержимое IFrame было отзывчивым, имея при этом горизонтальную прокрутку содержимого, поэтому вопрос заключался не в том, как имитировать прокрутку iframe , а в том, как добиться, чтобы ширина iframe была на 100%, т.е. этот фрейм Вот почему вышеупомянутый подход не работает в этом случае, потому что спроектированная отзывчивость была нарушена, и вам нужно прокрутить, чтобы увидеть полный контент, даже в тех местах, которые изначально вам не нужны.
Idra
1
Прошу прощения, я понял, что ввел вас в заблуждение по одному из комментариев. Iframe не прокручивается. В том-то и дело, что iframe не должен был прокручивать только части своего контента, т.е. div#ScrolledArea(в зеленом цвете) в моем примере. Я просто неправильно читал раньше. Но iframe не должен прокручивать, только изменяя размеры самого себя, основываясь на элементе контейнера, т.е. естьwidth: 100%;
Idra
18

Мне нужно было кроссбраузерное решение. Требования были:

  • необходимо для работы как на iOS, так и где-либо еще
  • нет доступа к контенту в iFrame
  • нужно прокрутить!

Основываясь на том, что я узнал от @Idra относительно scrolling = "no" в iOS и этой публикации о подгонке содержимого iFrame на экран в iOS, вот что у меня получилось. Надеюсь, это поможет кому-то =)

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);

}
gerbz
источник
1
проголосовал, но ... почему правило IE6 в классе "IOS"? :-)
J. Bruni
12

Проблема всех этих решений в том, что высота iframeникогда не меняется.

Это означает, что вы не сможете центрировать элементы внутри с iframeпомощью Javascript position:fixed;, или position:absolute;поскольку iframeсам по себе никогда не прокручивается.

Мое решение, подробно описанное здесь, заключается в том, чтобы обернуть все содержимое iframe внутри с divпомощью этого CSS:

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

Таким образом, Safari считает, что контент не имеет высоты, и позволяет вам iframeправильно назначить высоту . Это также позволяет вам позиционировать элементы так, как вы хотите.

Здесь вы можете увидеть быструю и грязную демонстрацию.

пирс
источник
1
Это единственное решение, которое сработало для меня. Конечно, его можно использовать только в том случае, если вы контролируете содержимое файла iframe, но в моем случае это я. Ура!
Винс
Хм. Ваш пример не работает на iOS?
BrandonReid
Это было 2 года назад, когда я написал это. Можете ли вы подать вопрос в репо?
Пирс
после того, как я потратил много часов на эту проблему с Ionic / Cordova на iOS, это единственное, что сработало. Спасибо!
Эндрю
1
Это потрясающе, единственное, что сработало, я потратил 1 день на поиск такого решения, как @Pier 100pts для вас
Carlos E
5

Эта проблема также присутствует в iOS Chrome.

Я просмотрел все решения выше, большинство из них очень хакерские.

Если вам не нужна поддержка старых браузеров, просто установите ширину iframe равной 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 */
}

Примечание. Проверьте поддержку единиц просмотра https://caniuse.com/#feat=viewport-units.

Пратхамеш Гарат
источник
1
Chrome для iOS - это просто Safari. Он использует WKWebView. Никакой другой движок веб-рендеринга в iOS не допускается.
Pier
3

Я работаю с ionic2 и конфигурации системы, как показано ниже


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

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



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

Для меня эта проблема была решена с помощью этого кода -
для тега html iframe -

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

См. Css того же, что и -


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

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

Положение собственности играет жизненно важную роль здесь, в моем случае.
позиция: относительная;

Это может вам тоже помочь !!!

S.Yadav
источник
0

Только CSS решение

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

Еще одна демонстрация здесь с HTML-страницей в iframe

4dgaurav
источник
Возможно, я неправильно реализую ваше решение, но когда я попробовал его на своем изолированном тестовом примере, оно не сработало вообще в iOS Safari 7.1 iPhone 4. Не могли бы вы подробнее рассказать, как это должно работать?
Идра
Хорошо, похоже, вы неправильно поняли проблему, проверьте эту ссылку, это ваш новый демонстрационный контент iframe, интегрированный без какого-либо дополнительного CSS, примененного к iframe. И если вы посмотрите на него в iOS Safari, он по-прежнему реагирует, потому что на этой странице нет горизонтальной прокрутки, которая заставила бы ширину iframe быть шире, чем область просмотра. Как описано в вопросе, на таком сайте вам не нужно ничего делать, чтобы iframe был отзывчивым.
Idra
так что именно вы хотите, чтобы он вёл себя, приведите пример для данной ссылки?
4dgaurav
0

У меня была проблема с шириной на панели содержимого, создавая горизонтальную полосу прокрутки для iframe. Оказалось, что изображение оказалось шире, чем ожидалось. Я смог решить эту проблему, установив для всех изображений максимальную ширину css в процентах.

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

img {
        max-width: 100%;
        height:auto;
    }
Доктор Аарон Дишно
источник
0

на самом деле у меня просто работало в ios отключение прокрутки

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

и лечение ОС с помощью скрипта.

Луис Росси
источник
0

Для меня решения CSS не работали. Но программная установка ширины делает свою работу. При загрузке iframe программно установите ширину:

 $('iframe').width('100%');
Умеров
источник