Como obter um IFrame para responder no iOS Safari?

134

O problema é que, quando você precisa usar IFrames para inserir conteúdo em um site, no mundo da web moderno espera-se que o IFrame também responda. Em teoria, é simples, basta usar <iframe width="100%"></iframe>ou definir a largura do CSS para, iframe { width: 100%; }no entanto, na prática, não é tão simples assim, mas pode ser.

Se o iframeconteúdo for totalmente responsivo e puder se redimensionar sem barras de rolagem internas, o iOS Safari será redimensionado iframesem problemas reais.

Se você considerar o seguinte código:

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

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

Então isso funciona sem problemas no iOS 7.1 Safari. Você pode alternar entre paisagem e retrato sem problemas.

insira a descrição da imagem aqui insira a descrição da imagem aqui

No entanto, basta alterar o CSS Content.html adicionando este:

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

Você obtém isto:

insira a descrição da imagem aqui insira a descrição da imagem aqui

Como você pode ver, embora o content.html conteúdo é totalmente sensível ( div # ScrolledArea tem overflow: scrollset) eo iframe width é de 100% do iframe ainda leva a toda a largura da div # ScrolledArea como se o transbordamento nem sequer existe. Demo

Em casos como esse, onde o iframeconteúdo possui áreas de rolagem, a questão é: como obter a iframeresposta, quando o conteúdo do iframe possui áreas de rolagem horizontal? O problema aqui não está no fato de o Content.html não ser responsivo, mas no fato de o Safari do iOS simplesmente redimensionar o iframe para que div#ScrolledAreaele fique totalmente visível.

Idra
fonte
Você pode compartilhar um link conosco? Você está dizendo que o iOS expandirá um iFrame para toda a largura da página, se a página tiver conteúdo com white-space: nowrapestilo?
DA.
Adicionei demos para o problema e para a solução. E não, o white-space: nowrapem si não é o problema. Estou simplesmente usando-o para obter uma largura extrema para div#ScrolledArea. O problema ocorre quando o conteúdo do IFrame possui áreas de rolagem horizontal. Se for esse o caso, o Safari do iOS simplesmente ignora as configurações de largura e mostra o conteúdo do furo e interrompe a capacidade de resposta do site.
Idra
Hmm ... Gostaria de saber se isso é um "recurso". Seria estranho ter uma área rolável (iFrame) que contenha conteúdo rolável. Seria algo muito difícil de interagir em uma tela de toque.
DA.
@DA É claro que este é um caso de sobrinha, e o que você disse pode ser verdade (depende da implementação, funciona para nós) e a maioria dos sites não tem áreas de rolagem horizontal, mas quando o faz ... você nem imagina quanto tempo eu gastei nisso. Mas isso pode ser um problema, mesmo se você tiver imagens ocultas e roladas com botões ou algo assim.
Idra
Parece que há perguntas relacionadas a isso: stackoverflow.com/questions/5267996/… Parece ser um 'recurso' do safari móvel ... está tentando garantir que o conteúdo esteja sendo dimensionado da maneira que o usuário pode ainda interage com ele. Não sei o que aconteceria se você tivesse conteúdo de rolagem em um iframe de rolagem ... como o Safari interpretaria um furto nos elementos de rolagem aninhados?
DA.

Respostas:

289

A solução para esse problema é realmente bastante simples e há duas maneiras de fazer isso. Se você tem controle sobre o Content.html , basta alterar a div#ScrolledArealargura do CSS para:

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

Basicamente, a idéia aqui é simples: você define o valor widthcomo algo menor que a janela de visualização (neste caso, largura do iframe) e a substitui min-width: 100%para permitir width: 100%que iOS Safari real substitua por padrão. O *width: 100%;código está lá para que o código permaneça compatível com o IE6, mas se você não se importa com o IE6, pode omiti-lo. Demo

insira a descrição da imagem aqui insira a descrição da imagem aqui

Como você pode ver agora, a div#ScrolledArealargura é realmente 100%, e a overflow: scroll;lata pode fazer isso e ocultar o conteúdo transbordante. Se você tiver acesso ao conteúdo do iframe, é preferível.

No entanto, se você não tiver acesso ao conteúdo do iframe (por qualquer motivo), poderá usar a mesma técnica no próprio iframe. Basta usar o mesmo CSS no iframe:

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

No entanto, há uma limitação nisso: você precisa desativar as barras de rolagem scrolling="no"no iframe para que isso funcione:

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

Se as barras de rolagem forem permitidas, isso não funcionará mais no iframe. Dito isso, se você modificar o Content.html , poderá manter a rolagem no iframe. Demo

Idra
fonte
1
Como o @NickGottlieb mencionado, eu tive que adicionar !importantao widthatributo para preparar o iframe responsivo-web-design em um iPhone 4 com iOS 7
#
@ ЮнгвиртТони Não deve ser necessário que a solução alternativa funcione, é possível que ela tenha widthsido definida anteriormente com !importantou um CSS de prioridade mais alta a tenha substituído. Em casos isolados no iPhone 4 iOS7, não era necessário.
Idra
Eu também não precisava! Importante. Funciona muito bem no iOS 8 também. Cheers
Sam Potts
Preciso de rolagem = não somente quando necessário, caso contrário, rolagem = sim. Então, o que devo estar detectando? Este é um problema do iOS? ou um problema no webkit? ou...?
Gerbz 28/04
@ggwarpig, esse é um problema do iOS, em que o Safari do iOS ativa automaticamente o atributo contínuo e você não pode substituí-lo. Se você tiver controle sobre o conteúdo, precisará modificá-lo para que, scrolling="yes"caso contrário, não haja maneira de corrigir isso. Para que a correção funcione no IFRAME, é necessário apenas scrolling="no"no IFRAME
Idra
24

O problema, ao que parece, é que o Mobile Safari se recusará a obedecer à largura do seu iFrame se o documento contido for maior do que o que você especificou. Exemplo:

http://jsbin.com/hapituto/1

Em um navegador de desktop, você verá um iFrame e um Div ambos configurados para 300px. O conteúdo é mais amplo, para que você possa rolar o iFrame.

No safari móvel, no entanto, você notará que o iFrame é expandido automaticamente para a largura do conteúdo.

Meu palpite é que essa é uma solução alternativa para problemas antigos com rolagem de conteúdo em uma página. No passado, se você tivesse um iframe de rolagem grande em um dispositivo de toque, ficaria "preso" no iframe, pois isso rolaria ao invés da própria página. Parece que a Apple decidiu que o comportamento padrão de um iFrame é 'sem rolagem' e se expande para evitá-lo.

Uma opção pode ser essa solução alternativa. Em vez de assumir que o iFrame rolará, coloque o iframe em uma DIV que você tem controle e deixe esse rolagem.

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

Exemplo de marcação:

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

No safari móvel, agora você pode rolar o conteúdo do iFrame agora totalmente expandido através da div que o contém.

O problema: isso parece realmente feio em um navegador de desktop, pois agora você tem barras de rolagem duplas. Portanto, você pode precisar fazer alguma detecção do navegador com o JS para contornar isso.

DA.
fonte
1
Eu ainda diria que isso não está no escopo da pergunta, porque a solução que você mostrou aqui é a maneira padrão de falsificar a rolagem iframe do furo no iOS Safari, mas levar em consideração esse problema do iOS é uma questão relacionada à rolagem do IFrame (conteúdo ou não), então é bom tê-lo aqui.
Idra
1
Acho que não entendi completamente sua pergunta. Pelo que entendi, o problema que você está enfrentando é que, no iOS, o Mobile Safari tenta impedir um iFrame de rolar em primeiro lugar e força uma largura sobre ele. Estou entendendo mal o seu problema?
DA.
Em essência, esse é o problema, apenas a solução necessária é diferente. No problema inicial, o conteúdo do IFrame era responsivo, ao mesmo tempo em que rolava horizontalmente o conteúdo, então a questão não era como emular a rolagem de iframe , mas como obter a largura do iframe 100%, ou seja, responsivo, enquanto você rolava horizontalmente o conteúdo com in esse iframe. É por isso que a abordagem acima não funciona nesse caso, porque a capacidade de resposta projetada foi interrompida e você precisa rolar para ver o conteúdo completo, mesmo em locais que foram projetados por você normalmente não precisaria.
Idra
1
Peço desculpas, percebi que enganei você em um dos comentários. O iframe não está rolando. Esse era o ponto, o iframe não deveria estar rolando apenas partes de seu conteúdo, ou seja, o div#ScrolledArea(em verde) no meu exemplo. Acabei de ler errado antes. Mas o iframe não deve ser rolagem única redimensionar-se com base no elemento contentor ou seja, terwidth: 100%;
Idra
18

Eu precisava de uma solução entre navegadores. Os requisitos foram:

  • necessário para trabalhar no iOS e em outros lugares
  • não tem acesso ao conteúdo no iFrame
  • precisa rolar!

Com base no que aprendi no @Idra sobre rolagem = "não" no iOS e nesta postagem sobre como ajustar o conteúdo do iFrame à tela no iOS, aqui está o que eu acabei. Espero que ajude alguém =)

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
fonte
1
votado, mas ... por que o IE6 governa na classe "ios"? :-)
J. Bruni
12

O problema com todas essas soluções é que a altura do iframenunca muda realmente.

Isso significa que você não poderá centralizar elementos dentro do iframeJavascript usando position:fixed;, ou position:absolute;porque o iframepróprio nunca rola.

Minha solução detalhada aqui é agrupar todo o conteúdo do iframe dentro de um divusando este CSS:

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

Dessa forma, o Safari acredita que o conteúdo não tem altura e permite atribuir a altura do conteúdo iframecorretamente. Isso também permite que você posicione os elementos da maneira que desejar.

Você pode ver uma demonstração rápida e suja aqui.

Pier
fonte
1
Esta é a única solução que funcionou para mim. Obviamente, ele só pode ser usado se você controlar o conteúdo do iframe, mas no meu caso, eu faço. Felicidades!
Vince
Hmm. Seu exemplo não parece ser responsivo no iOS?
precisa saber é o seguinte
Foi há 2 anos quando eu escrevi isso. Você pode registrar um problema no repositório?
Pier
depois de desperdiçar horas e horas com o Ionic / Cordova no iOS, essa é a única coisa que funcionou. obrigado!
Andrew Andrew
1
Isto é incrível, o único que funcionou, eu passei um dia de procura de uma solução como esta 100pts @Pier para você
Carlos E
5

Esse problema também está presente no iOS Chrome.

Olhei através de todas as soluções acima, a maioria é muito hacky.

Se você não precisar de suporte para navegadores mais antigos, defina a largura do iframe como 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 */
}

Nota: verifique o suporte para unidades de viewport https://caniuse.com/#feat=viewport-units

Prathamesh Gharat
fonte
1
O Chrome para iOS é apenas o Safari abaixo. Ele usa o WKWebView. Nenhum outro mecanismo de renderização da web é permitido no iOS.
Pier
3

Eu estou trabalhando com ionic2 e configuração do sistema é como abaixo-


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

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



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

Para mim, esse problema foi resolvido com este código -
para a tag iframe html -

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

Veja css da mesma 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%;
}

A propriedade Position desempenha um papel vital aqui no meu caso.
posição: relativa;

Pode ajudar você também !!!

S.Yadav
fonte
0

Solução apenas 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

Outra demonstração aqui com a página HTML no iframe

4dgaurav
fonte
Talvez esteja implementando sua solução incorretamente, mas quando tentei com meu caso de teste isolado, ele não funcionou no iOS Safari 7.1 iPhone 4. Você poderia elaborar como isso deve funcionar?
Idra
OK, parece que você não entendeu o problema. Confira este link: é o seu novo conteúdo de demonstração iframe integrado sem nenhum CSS adicional aplicado ao iframe. E se você examiná-lo no iOS Safari, ele ainda será responsivo, porque esta página não possui rolagem horizontal que forçaria a largura do iframe a ser maior que a janela de visualização. Conforme descrito na pergunta, em um site como esse, você não precisa fazer nada para que o iframe seja responsivo.
Idra
Então, o que exatamente você quer que ele se comporte, dê um exemplo para o seu link fornecido?
precisa saber é o seguinte
0

Eu tive um problema com a largura no painel de conteúdo, criando uma barra de rolagem horizontal para o iframe. Verificou-se que uma imagem estava mantendo a largura maior que o esperado. Consegui resolvê-lo definindo todas as imagens css max-width como um percentual.

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

img {
        max-width: 100%;
        height:auto;
    }
Dr. Aaron Dishno
fonte
0

na verdade, para mim, apenas trabalhou no iOS desativando o pergaminho

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

e tratando o SO via script.

Luiz Rossi
fonte
0

Para mim, as soluções CSS não funcionaram. Mas definir a largura programaticamente faz o trabalho. No carregamento do iframe, defina a largura programaticamente:

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