Изменение размера iframe на основе содержимого

Я работаю над приложением, похожим на iGoogle. Контент из других приложений (в других доменах) отображается с помощью iframe.

Как изменить размер окон iframe по высоте их содержимого?

Я пытался расшифровать javascript, который использует Google, но он запутан, и поиск в Интернете до сих пор был бесплодным.

Обновлять: Обратите внимание, что контент загружается из других доменов, поэтому применяется политика одного происхождения.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
506
0
320 935
22
Перейти к ответу Данный вопрос помечен как решенный

Ответы 22

Это немного сложно, поскольку вам нужно знать, когда страница iframe загружена, что затруднительно, когда вы не контролируете ее содержимое. Можно добавить обработчик загрузки в iframe, но я пробовал это в прошлом, и он имеет совершенно разное поведение в разных браузерах (не угадайте, кто больше всего раздражает ...). Вероятно, вам придется добавить функцию на страницу iframe, которая выполняет изменение размера и вставляет некоторый скрипт в контент, который либо прослушивает события загрузки, либо события изменения размера, который затем вызывает предыдущую функцию. Я думаю добавить функцию на страницу, так как вы хотите убедиться, что она безопасна, но я понятия не имею, насколько легко это будет сделать.

Что-то в этом роде, я считаю, должно сработать.

parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;

Загрузите его вместе с телом на содержимое iframe.

Это невозможно, поскольку содержимое iFrames загружается из других доменов, поэтому попытка сделать это приведет к ошибке, например, из Firefox: «Отказано в разрешении на получение свойства Window.document».

larssg 30.09.2008 18:23

Решение на http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html отлично работает (использует jQuery):

<script type=”text/javascript”>
  $(document).ready(function() {
    var theFrame = $(”#iFrameToAdjust”, parent.document.body);
    theFrame.height($(document.body).height() + 30);
  });
</script>

Не знаю, нужно ли прибавлять 30 к длине ... 1 у меня сработал.

К вашему сведению: если у вас уже есть атрибут «высота» в iFrame, это просто добавляет style = «height: xxx». Возможно, это не то, что вам нужно.

Как раз то, что мне было нужно, так как я не занимаюсь междоменным, +1 для действительного html.

WildJoe 17.01.2011 05:31

Гаджеты iGoogle должны активно реализовывать изменение размера, поэтому я предполагаю, что в междоменной модели вы не сможете сделать это без какого-либо участия удаленного контента. Если ваш контент может отправить сообщение с новым размером на страницу контейнера, используя типичные методы междоменного взаимодействия, то все остальное просто.

Ответ принят как подходящий

У нас был этот тип проблемы, но немного противоположный вашей ситуации - мы предоставляли контент с iframe сайтам в других доменах, поэтому та же политика происхождения также был проблемой. После многих часов, потраченных на поиски в Google, мы в конце концов нашли (в некоторой степени ...) работоспособное решение, которое вы, возможно, сможете адаптировать к своим потребностям.

Существует способ обойти ту же политику происхождения, но он требует изменений как в содержимом iframed, так и в странице кадрирования, поэтому, если у вас нет возможности запрашивать изменения с обеих сторон, этот метод не будет для вас очень полезным, Боюсь.

Есть особенность браузера, которая позволяет нам обходить одну и ту же политику происхождения - javascript может взаимодействовать либо со страницами в собственном домене, либо со страницами, которые он имеет iframe, но никогда не страницами, на которых он размещен, например если у тебя есть:

 www.foo.com/home.html, which iframes
 |-> www.bar.net/framed.html, which iframes
     |-> www.foo.com/helper.html

тогда home.html может взаимодействовать с framed.html (iframe) и helper.html (тот же домен).

 Communication options for each page:
 +-------------------------+-----------+-------------+-------------+
 |                         | home.html | framed.html | helper.html |
 +-------------------------+-----------+-------------+-------------+
 | www.foo.com/home.html   |    N/A    |     YES     |     YES     |
 | www.bar.net/framed.html |    NO     |     N/A     |     YES     |
 | www.foo.com/helper.html |    YES    |     YES     |     N/A     |
 +-------------------------+-----------+-------------+-------------+

framed.html может отправлять сообщения helper.html (iframed), но нетhome.html (дочерний элемент не может взаимодействовать с родительским в междоменном режиме).

Ключевым моментом здесь является то, что helper.html может получать сообщения от framed.html, а также может общаться - от home.html.

По сути, когда framed.html загружается, он определяет свою высоту, сообщает helper.html, который передает сообщение home.html, который затем может изменить размер iframe, в котором находится framed.html.

Самый простой способ, который мы нашли для передачи сообщений от framed.html к helper.html, - это аргумент URL. Для этого в framed.html есть iframe с указанным src=''. Когда его onload срабатывает, он оценивает свою высоту и устанавливает src iframe в этой точке на helper.html?height=N.

Здесь есть объяснение того, как facebook обрабатывает это, что может быть немного яснее, чем мое выше!


Код

В www.foo.com/home.html требуется следующий код javascript (кстати, его можно загрузить из файла .js в любом домене ..):

<script>
  // Resize iframe to full height
  function resizeIframe(height)
  {
    // "+60" is a general rule of thumb to allow for differences in
    // IE & and FF height reporting, can be adjusted as required..
    document.getElementById('frame_name_here').height = parseInt(height)+60;
  }
</script>
<iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>

В www.bar.net/framed.html:

<body onload = "iframeResizePipe()">
<iframe id = "helpframe" src='' height='0' width='0' frameborder='0'></iframe>

<script type = "text/javascript">
  function iframeResizePipe()
  {
     // What's the page height?
     var height = document.body.scrollHeight;

     // Going to 'pipe' the data to the parent through the helpframe..
     var pipe = document.getElementById('helpframe');

     // Cachebuster a precaution here to stop browser caching interfering
     pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();

  }
</script>

Состав www.foo.com/helper.html:

<html> 
<!-- 
This page is on the same domain as the parent, so can
communicate with it to order the iframe window resizing
to fit the content 
--> 
  <body onload = "parentIframeResize()"> 
    <script> 
      // Tell the parent iframe what height the iframe needs to be
      function parentIframeResize()
      {
         var height = getParam('height');
         // This works as our parent's parent is on our domain..
         parent.parent.resizeIframe(height);
      }

      // Helper function, parse param from request string
      function getParam( name )
      {
        name = name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");
        var regexS = "[\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if ( results == null )
          return "";
        else
          return results[1];
      }
    </script> 
  </body> 
</html>

Только одно! Когда swf вернется к своему нормальному размеру, как вы собираетесь изменить размер iframe? У вас есть iframeResizePipe на таймере или он снова вызывается swf? В моей компании, когда есть вызов js в swf, чтобы мы точно знали, когда он меняет размер

AntonioCS 19.01.2009 00:45

Отлично, спасибо! Я сделал пару дополнений: используйте jQuery, чтобы получить высоту тела в framed.html (проблема с FF, тело продолжало расти): var height = $ (document.body) .height (); Использование события загрузки тела для создания кадра в home.html аналогично вашему подходу в framed.html. Адреса, не обновляющие фрейм при обновлении в FF и Safari.

Abdullah Jibaly 31.08.2009 20:50

Гений! В дополнение к дополнениям Абдуллы: вместо того, чтобы настраивать загрузку тела для вызова parentIframeResize(), я использовал JQuery для отслеживания как загрузки страницы, так и любых событий изменения размера: $(document).ready(iframeResizePipe); $(window).resize(iframeResizePipe); Это позволяет мне установить iframe width = "100%" и, если ширина окна изменится, чтобы сделать перенос текста или что-то внутренний фрейм распознает, что его размер должен быть изменен.

StriplingWarrior 22.05.2010 00:51

Так что это решение только в том случае, если вы сможете убедить владельцев сайта изменить код на своей странице. Если вы не можете этого сделать, значит, это не сработает.

Volomike 02.06.2010 01:14

Если обрамлено (bar.net, первый iframe) https, может ли он получить доступ к домашней странице (главной странице) через parent.parent.resizeIframe (height); ?

Keyo 06.07.2010 04:50

Вызов parent.parent.resizeIFrame () не работает в Opera. Сообщение об ошибке: «Страница в общедоступном Интернете запрашивает данные из вашей частной интрасети. По соображениям безопасности автоматический доступ заблокирован, но вы можете продолжить.» .... каким-либо способом получить доступ к родительскому объекту без вызова этой ошибки?

frankadelic 20.07.2010 10:36

Вслед за этим с новой версией Firefox, наряду с Chrome, Safari и IE ... при переходе между страницами размер окна продолжает изменяться и увеличивается до прежнего размера. Кажется, это больше не работает: /

Petrogad 01.09.2010 17:47

Я предлагаю дать iframe id = frame_name_here атрибут высоты по умолчанию, например height = "2000". Это означает, что когда страница загружается, содержимое в рамке становится видимым. Когда происходит изменение размера, «мерцания» не происходит. Размер уменьшается / увеличивается ниже сгиба страницы. Если вы знаете максимальную высоту вашего iframed-контента, используйте это значение ... это также улучшает работу с noscript.

Chris Jacob 09.09.2010 06:21

@StriplingWarrior Я мог бы представить (и поправить меня, если я ошибаюсь), но разве $(document).ready(iframeResizePipe); не вызовет изменение размера слишком рано? ... то есть до того, как изображения были извлечены и повлияли на рост? Может быть нормально, если вы укажете высоту на всех своих изображениях <img height = "value" /> ... просто подумайте вслух.

Chris Jacob 09.09.2010 06:28

предложить <iframe id = "helpframe" style = "display:none;"></iframe> ... в IE8 iframe был виден в макете страницы.

Chris Jacob 09.09.2010 07:04

Предложите: <iframe id='frame_name_here' name='frame_name_here' src='http://www.bar.net/framed.html'></iframe>. Потом function iframeResizePipe(){if (window.name === 'frame_name_here'){ .. do the resize only if the page is contained inside the iframe .. }}. Это позволяет избежать получения сообщения в Firebug о Permission denied for <http://www.foo.com> to get property Window.resizeIframe from <http://localhost>.[Break on this error] parent.parent.resizeIframe(height);.

Chris Jacob 09.09.2010 07:48

Кроме того, это не работает, если у вас есть динамически изменяющееся содержимое на страницах.

Petrogad 09.09.2010 22:47

Может кто-нибудь объяснить, что означает, что Home может общаться с Framed, но Framed не может общаться с Home. Вопрос в том, кто может начать коммуникационный процесс?

Dan Roberts 27.07.2011 23:17

Это все еще работает? Это похоже на непреднамеренную функцию (которая может быть «исправлена» при автоматическом обновлении браузера).

finnw 26.09.2011 21:59

@Frederico, этот подход все еще работает, но решение необходимо пересмотреть, чтобы оно работало в самых последних версиях FF и Chrome. Высота прокрутки будет неправильно использовать высоту iframe, если она больше, чем отображаемая страница. Это заставляет iframe потенциально увеличиваться на 60 пикселей с каждым поворотом страницы. Необходимое исправление - наличие элемента с идентификатором внутри HTML-кода во фрейме. Получите его высоту прокрутки вместо документа, и он будет работать как чемпион.

Thomas 17.11.2011 00:55

Как и сказал @Frederico, в новой версии Firefox высота продолжает добавлять предыдущий размер, однако вы можете исправить это, не добавляя дополнительную высоту в этом коде: document.getElementById('frame_name_here').height = parseInt(height)+60;. Просто используйте заданную высоту, и это решит проблему, но если вам нужно немного места в вашем контенте, просто добавьте немного отступов в тело framed.html, я думаю, что это должно решить проблему.

adods 14.03.2012 14:03

Есть ли какие-либо последствия для безопасности при получении URL-адреса framehelper.html в качестве параметра строки запроса?

Alex J 30.09.2012 22:29

Спасибо за отличное объяснение! Еще одно возможное улучшение сценария - выбрать все теги img через jQuery и привязать их к событиям load, чтобы вы повторно обновляли высоту iFrame каждый раз, когда изображение успешно загружается, или запускали изменение размера iFrame только после того, как все изображения были загружен. Это связано с тем, что высота содержимого может измениться при загрузке изображений из-за фактических размеров изображения, переноса текста и т. д.

Mark Cassar 21.03.2013 13:50

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

TMS 30.10.2013 21:35

Обращаясь к вашему столу - вы говорите, что помощник может общаться с подставным? Я бы сказал, не может по той же причине, по которой обрамленный не может общаться с домом. Разве это не ошибка?

TMS 18.01.2014 15:59

@ChrisJacob Хороший совет по установке начальной высоты. Вместо этого я установил min-height в CSS.

andrewtweber 26.03.2014 21:46

Это действительно устаревший ответ, для получения лучших вариантов см. stackoverflow.com/questions/14334154/…

David Bradshaw 10.06.2014 03:23

Большое спасибо. Большое спасибо за этот ответ :). Между тем, я добавил этот function resizeIframe(_height) {$("#frame_name_here").height(_height) } на свой сайт www.foo.com для установки высоты iframe.

Selvamani 11.06.2014 22:14

Хороший пост, но опять же, как поймать изменение размера дочернего iframe? Единственное, что вам часто нужно, это автоматическая высота, чтобы предотвратить изменение размера полос прокрутки iframe.

Rantiev 12.09.2014 14:20

Я в той же лодке ... поставляю контент во фреймах в другие домены. Основываясь на вашем решении, вы говорите, что вам нужно создать файл helper.html из каждого домена, который хочет добавить ваш контент?

Michael Yaeger 07.05.2016 07:28

К сожалению, это больше не работает. Я тщательно реализовал это, но получил следующую ошибку javascript в консоли Chrome: Uncaught DOMException: заблокировал фрейм с источником «example.com» от доступа к фрейму с перекрестным источником.

Stefan 14.02.2017 17:20

Обновление 2017: в Chrome я могу вызвать window.parent.postMessage (data, '*'); и родительский фрейм может получить сообщение. Он работает с перекрестным происхождением.

Alexander Taylor 20.12.2017 03:49

Если вам не нужно обрабатывать содержимое iframe из другого домена, попробуйте этот код, он полностью решит проблему, и это просто:

<script language = "JavaScript">
<!--
function autoResize(id){
    var newheight;
    var newwidth;

    if (document.getElementById){
        newheight=document.getElementById(id).contentWindow.document .body.scrollHeight;
        newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth;
    }

    document.getElementById(id).height= (newheight) + "px";
    document.getElementById(id).width= (newwidth) + "px";
}
//-->
</script>

<iframe src = "usagelogs/default.aspx" width = "100%" height = "200px" id = "iframe1" marginheight = "0" frameborder = "0" onLoad = "autoResize('iframe1');"></iframe>

Возможно, будет более оптимальным передать сам элемент в функцию, чтобы избежать всех этих document.getElementById(id), которые у вас есть, и упростить код.

Muhd 14.10.2011 01:02

Это не работает для меня, поскольку contentWindow.document.body.scrollHeight содержит 0, а не реальную высоту.

kroiz 01.11.2011 18:38

Это решение, как и все другие, которые я пробовал, работает, только если высота увеличивается, если с высокой страницы вы переходите к более короткой, высота по-прежнему устанавливается в соответствии с высотой первой. Кто-нибудь нашел решение этой проблемы?

Eugenio 31.12.2012 18:41

@Eugenio и все остальные, включая меня, чтобы исправить эту последнюю проблему: см. stackoverflow.com/questions/3053072/…. Прежде чем запрашивать высоту документа внутри iframe, вы должны установить высоту объекта iframe на "auto". Обратите внимание, что вы должны использовать style.height, а не только высоту, как в ответе выше.

Kyle 10.01.2013 01:41

@ Кайл, это работает, спасибо! По-прежнему существует остаточная проблема с FF: рассчитанная высота всегда на несколько пикселей меньше необходимой, поэтому вы всегда видите вертикальную полосу прокрутки ... добавление + кое-что не решает проблему для меня.

Eugenio 10.01.2013 20:48

Я не понимаю ... вы проверяете наличие document.getElementById, а затем все равно вызываете его за пределами проверенной области?

Legolas 06.02.2013 20:45

Меня устраивает! Я встраиваю другой скрипт, который отображает созданный пользователем HTML из того же домена, он не портит мои стили.

MikeGA 26.06.2013 04:42

Также обратите внимание, что это не работает для iframe с атрибутом sandbox.

seriyPS 02.03.2014 03:55

вопрос касается перекрестного домена, но ваш ответ конкретно начинается: «Если вам не нужно обрабатывать содержимое iframe из другого домена». так что это, как написал @kevin, и (вместе с текущим официально выбранным ответом от ConroyP) не может считаться полным ответом - который, похоже, МОЖЕТ существовать (см. другие ответы ниже).

pashute 19.02.2018 10:04

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

http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/

Таким образом, предоставленный код iframe будет иметь сопутствующую таблицу стилей, например, так ...

<link href = "http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel = "stylesheet" type = "text/css" />
 <iframe id = "iframe_widget" src = "http://your.site/path/to/content?content_id=1234" frameborder = "0" width = "100%" scrolling = "no"></iframe>

Для этого требуется, чтобы логика на стороне сервера могла вычислять размеры отображаемого содержимого iframe.

Ссылка не работает. Не могли бы вы поделиться соответствующим кодом в своем ответе, чтобы он оставался актуальным для этой темы?

zed 11.03.2019 22:26

https://developer.mozilla.org/en/DOM/window.postMessage

window.postMessage()

window.postMessage is a method for safely enabling cross-origin communication. Normally, scripts on different pages are only allowed to access each other if and only if the pages which executed them are at locations with the same protocol (usually both http), port number (80 being the default for http), and host (modulo document.domain being set by both pages to the same value). window.postMessage provides a controlled mechanism to circumvent this restriction in a way which is secure when properly used.

Summary

window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called. (Other standard properties of events are present with their expected values.)

Библиотека iFrame-Resizer использует postMessage для сохранения размера iFrame в соответствии с его содержимым, а также MutationObserver для обнаружения изменений содержимого и не зависит от jQuery.

https://github.com/davidjbradshaw/iframe-resizer

jQuery: совершенство междоменного написания сценариев

http://benalman.com/projects/jquery-postmessage-plugin/

Есть демонстрация изменения размера окна iframe ...

http://benalman.com/code/projects/jquery-postmessage/examples/iframe/

В этой статье показано, как удалить зависимость от jQuery ... Plus содержит много полезной информации и ссылок на другие решения.

http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/

Пример Barebones ...

http://onlineaspect.com/uploads/postmessage/parent.html

Рабочий проект HTML 5 на window.postMessage

http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages

Джон Ресиг о межоконном обмене сообщениями

http://ejohn.org/blog/cross-window-messaging/

postMessage сам по себе не является кроссбраузерным, но плагин jQuery, кажется, хорошо справляется с его подделкой, когда это необходимо. Единственная реальная проблема - это «мусор», который добавляется в строку URL в тех случаях, когда postMessage не поддерживается.

Herms 01.08.2011 19:50

postMessage похоже на X-Browser. Только IE должен иметь дело с ошибками или вещами: 1. Связь только между фреймами или фреймами 2. Только возможность отправки строк. См .: caniuse.com/x-doc-messaging

Christian Kuetbach 23.01.2013 22:49

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

hitautodestruct 13.07.2014 19:21

periscopedata использует postMessage, и если он им подходит, то и нам. Вот их документы: doc.periscopedata.com/docv2/embed-api-options

Yevgeniy Afanasyev 26.07.2017 04:03

Если вы хотите уменьшить масштаб веб-страницы, чтобы она соответствовала размеру окна iframe:

  1. Вы должны изменить размер iframe, чтобы он соответствовал содержимому
  2. Затем вы должны уменьшить масштаб всего iframe с загруженным содержимым веб-страницы.

Вот пример:

<div id = "wrap">
   <IFRAME ID = "frame" name = "Main" src  = "http://www.google.com" />
</div>

<style type = "text/css">
    #wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; }
    #frame { width: 900px; height: 600px; border: 1px solid black; }
    #frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-origin: 0 0; }
</style>

У меня есть простое решение, требующее, чтобы вы определили ширину и высоту ссылки, попробуйте (работает с большинством браузеров):

<a href='#' onClick = " document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>

Я реализую решение ConroyP frame-in-frame для замены решения, основанного на настройке document.domain, но обнаружил, что довольно сложно правильно определить высоту содержимого iframe в разных браузерах (тестирование с FF11, Ch17 и IE9 прямо сейчас ).

ConroyP использует:

var height = document.body.scrollHeight;

Но это работает только при начальной загрузке страницы. Мой iframe имеет динамический контент, и мне нужно изменить размер iframe для определенных событий.

В итоге я использовал разные свойства JS для разных браузеров.

function getDim () {
    var body = document.body,
        html = document.documentElement;

    var bc = body.clientHeight;
    var bo = body.offsetHeight;
    var bs = body.scrollHeight;
    var hc = html.clientHeight;
    var ho = html.offsetHeight;
    var hs = html.scrollHeight;

    var h = Math.max(bc, bo, bs, hc, hs, ho);

    var bd = getBrowserData();

    // Select height property to use depending on browser
    if (bd.isGecko) {
        // FF 11
        h = hc;
    } else if (bd.isChrome) {
        // CH 17
        h = hc;
    } else if (bd.isIE) {
        // IE 9
        h = bs;
    }

    return h;
}

getBrowserData () - это функция обнаружения браузером, "вдохновленная" http://docs.sencha.com/core/source/Ext.html#method-Ext-apply Ext Core

Это хорошо работало для FF и IE, но потом возникли проблемы с Chrome. Одной из них была проблема с синхронизацией, по-видимому, Chrome требуется некоторое время, чтобы установить / определить высоту iframe. И тогда Chrome также никогда не возвращал высоту содержимого в iframe правильно, если iframe был выше содержимого. Это не будет работать с динамическим контентом при уменьшении высоты.

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

function resize () {
    // Reset the iframes height to a low value.
    // Otherwise Chrome won't detect the content height of the iframe.
    setIframeHeight(150);

    // Delay getting the dimensions because Chrome needs
    // a few moments to get the correct height.
    setTimeout("getDimAndResize()", 100);
}

Код не оптимизирован, это результат моего тестирования :)

Надеюсь, кто-то сочтет это полезным!

Самый простой способ с помощью jQuery:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});

Не перекрестный домен по запросу.

willem 24.04.2013 13:41

Вот подход jQuery, который добавляет информацию в json через атрибут src iframe. Вот демонстрация, измените размер и прокрутите это окно ... получившийся URL-адрес с json выглядит так ... http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight:571}#

Вот скрипт с исходным кодом http://jsfiddle.net/zippyskippy/RJN3G/

function updateLocation(){

    var loc = window.location.href;
    window.location.href = loc.replace(/#{.*}#/,"") 
        + "#{docHeight:"+$(document).height() 
        + ",windowHeight:"+$(window).height()
        + ",scrollHeight:"+$(window).scrollTop()
        +"}#";

};

//setInterval(updateLocation,500);

$(window).resize(updateLocation);
$(window).scroll(updateLocation);

<html>
<head>
<script>
function frameSize(id){
var frameHeight;

document.getElementById(id).height=0 + "px";
if (document.getElementById){
    newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;    
}

document.getElementById(id).height= (frameHeight) + "px";
}
</script>
</head>

<body>

<iframe id = "frame"  src = "startframe.html" frameborder = "0" marginheight = "0" hspace=20     width = "100%" 

onload = "javascript:frameSize('frame');">

<p>This will work, but you need to host it on an http server, you can do it locally.    </p>
</body>
</html>

получить высоту содержимого iframe, затем передать ее этому iframe

 var iframes = document.getElementsByTagName("iframe");
 for(var i = 0, len = iframes.length; i<len; i++){
      window.frames[i].onload = function(_i){
           return function(){
                     iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px";
                     }
      }(i);
 }

Не могли бы вы добавить какое-нибудь описание того, почему ваш код отвечает на вопрос?

rhughes 11.12.2013 07:14

может быть немного поздно, так как все остальные ответы старше :-), но ... вот мое решение. Протестировано в реальных FF, Chrome и Safari 5.0.

css:

iframe {border:0; overflow:hidden;}

javascript:

$(document).ready(function(){
    $("iframe").load( function () {
        var c = (this.contentWindow || this.contentDocument);
        if (c.document) d = c.document;
        var ih = $(d).outerHeight();
        var iw = $(d).outerWidth();
        $(this).css({
            height: ih,
            width: iw
        });
    });
});

Надеюсь, это кому-нибудь поможет.

@pashute - вы имеете в виду "перекрестный домен"?

Luke 17.02.2018 08:22

Извините. Имеется в виду: не работает кросс-платформенный ... Вот общедоступная суть: gist.github.com/pashute/c4705ce7f767f50fdf56d0030ecf9192 Получает отказ в выполнении ошибки. Изменение скрипта на type = "text / javascript" не помогает. Не устанавливайте ширину и высоту iframe (скажем, 80%).

pashute 19.02.2018 10:53

Наконец, я нашел другое решение для отправки данных на родительский сайт из iframe с помощью window.postMessage(message, targetOrigin);. Здесь я объясняю, как я это сделал.

Сайт A = http://foo.com Сайт B = http://bar.com

SiteB загружается внутри сайта SiteA

На сайте SiteB есть эта строка

window.parent.postMessage("Hello From IFrame", "*"); 

или же

window.parent.postMessage("Hello From IFrame", "http://foo.com");

Тогда siteA имеет следующий код

// Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers.
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];


var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
   alert(e.data);
   // Do whatever you want to do with the data got from IFrame in Parent form.
}, false); 

Если вы хотите добавить безопасное соединение, вы можете использовать это условие if в eventer(messageEvent, function (e) {}).

if (e.origin == 'http://iframe.example.com') {
    alert(e.data); 
    // Do whatever you want to do with the data got from IFrame in Parent form.
}

Для IE

Внутри IFrame:

 window.parent.postMessage('{"key":"value"}','*');

Снаружи:

 eventer(messageEvent, function (e) {
   var data = jQuery.parseJSON(e.data);
   doSomething(data.key);
 }, false);

Работа с jquery при загрузке (кроссбраузерность):

 <iframe src = "your_url" marginwidth = "0"  marginheight = "0" scrolling = "No" frameborder = "0"  hspace = "0" vspace = "0" id = "containiframe" onload = "loaderIframe();" height = "100%"  width = "100%"></iframe>

function loaderIframe(){
var heightIframe = $('#containiframe').contents().find('body').height();
$('#frame').css("height", heightFrame);
 }  

при изменении размера на адаптивной странице:

$(window).resize(function(){
if ($('#containiframe').length !== 0) {
var heightIframe = $('#containiframe').contents().find('body').height();
 $('#frame').css("height", heightFrame);
}
});

Этот ответ применим только к веб-сайтам, использующим Bootstrap. Функция адаптивного встраивания в Bootstrap выполняет свою работу. Он основан на ширине (а не высоте) содержимого.

<!-- 16:9 aspect ratio -->
<div class = "embed-responsive embed-responsive-16by9">
  <iframe class = "embed-responsive-item" src = "http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe>
</div>

jsfiddle: http://jsfiddle.net/00qggsjj/2/

http://getbootstrap.com/components/#responsive-embed

Это работает для встраивания видео, но если я хочу встроить веб-страницу с высотой, она получает прокрутку и странную высоту.

cabaji99 29.09.2016 18:20

Используя jQuery:

parent.html

<body>
<script type = "text/javascript" src = "https://code.jquery.com/jquery-2.1.4.min.js"></script>
<style>
iframe {
    width: 100%;
    border: 1px solid black;
}
</style>
<script>
function foo(w, h) {
    $("iframe").css({width: w, height: h});
    return true;  // for debug purposes
}
</script>
<iframe src = "child.html"></iframe>
</body>

child.html

<body>
<script type = "text/javascript" src = "https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(function() {
    var w = $("#container").css("width");
    var h = $("#container").css("height");

    var req = parent.foo(w, h);
    console.info(req); // for debug purposes
});
</script>
<style>
body, html {
    margin: 0;
}
#container {
    width: 500px;
    height: 500px;
    background-color: red;
}
</style>
<div id = "container"></div>
</body>

Это старая ветка, но в 2020 году это все еще актуальный вопрос. Я на самом деле опубликовал этот ответ в другом старом потоке ^^ (https://stackoverflow.com/a/64110252/4383587)


Просто хотел поделиться своим решением и волнением. Мне потребовалось целых четыре дня интенсивных исследований и неудач, но я думаю, что нашел изящный способ сделать фреймы полностью адаптивными! Ура!

Я пробовал массу разных подходов ... Я не хотел использовать туннель двусторонней связи, как в случае с postMessage, потому что это неудобно для одного и того же происхождения и сложно для кросс-происхождения (поскольку ни один администратор не хочет открывать двери и реализовывать это от вашего имени).

Я пробовал использовать MutationObservers, и мне все еще требовалось несколько прослушивателей событий (изменение размера, щелчок, ..), чтобы гарантировать, что каждое изменение макета обрабатывается правильно. - Что, если скрипт переключает видимость элемента? Или что, если он динамически предварительно загружает больше контента по запросу? - Другая проблема заключалась в получении откуда-то точной высоты содержимого iframe. Большинство людей предлагают использовать scrollHeight или offsetHeight или их комбинацию с помощью Math.max. Проблема в том, что эти значения не обновляются, пока элемент iframe не изменит свои размеры. Для этого вы можете просто перезагрузить iframe.height = 0 перед тем, как брать scrollHeight, но на этот счет есть еще больше предостережений. Итак, к черту это.

Затем у меня появилась еще одна идея поэкспериментировать с requestAnimationFrame, чтобы избавиться от ада моих событий и наблюдателей. Теперь я мог немедленно реагировать на каждое изменение макета, но у меня по-прежнему не было надежного источника, из которого можно было бы сделать вывод о высоте содержимого iframe. И тогда я случайно обнаружил getComputedStyle! Это было просветление! Все просто щелкнуло.

Что ж, посмотрите код, который я смог извлечь из своих бесчисленных попыток.

function fit() {
    var iframes = document.querySelectorAll("iframe.gh-fit")

    for(var id = 0; id < iframes.length; id++) {
        var win = iframes[id].contentWindow
        var doc = win.document
        var html = doc.documentElement
        var body = doc.body
        var ifrm = iframes[id] // or win.frameElement

        if (body) {
            body.style.overflowX = "scroll" // scrollbar-jitter fix
            body.style.overflowY = "hidden"
        }
        if (html) {
            html.style.overflowX = "scroll" // scrollbar-jitter fix
            html.style.overflowY = "hidden"
            var style = win.getComputedStyle(html)
            ifrm.width = parseInt(style.getPropertyValue("width")) // round value
            ifrm.height = parseInt(style.getPropertyValue("height"))
        }
    }

    requestAnimationFrame(fit)
}

addEventListener("load", requestAnimationFrame.bind(this, fit))

Вот и все, да! - В вашем HTML-коде напишите <iframe src = "page.html" class = "gh-fit gh-fullwidth"></iframe>. gh-fit - это просто поддельный класс CSS, используемый для определения того, на какие элементы iframe в вашей DOM должен воздействовать скрипт. gh-fullwidth - это простой класс CSS с одним правилом width: 100%;.

Приведенный выше сценарий автоматически выбирает все фреймы из DOM, которым назначен класс .gh-fit. Затем он получает и использует предварительно рассчитанные значения стиля для ширины и высоты из document.getComputedStyle(iframe), которые всегда содержат идеальный размер этого элемента !!! Просто отлично!

Обратите внимание, что это решение не работает с разными источниками (как и любое другое решение без стратегии двусторонней связи, такой как IFrameResizer). JS просто не может получить доступ к DOM iframe, если он вам не принадлежит.

Единственное другое решение с перекрестным происхождением, которое я могу придумать, - это использовать прокси, например https://github.com/gnuns/allorigins. Но это потребует глубокого копирования каждого запроса, который вы делаете - другими словами, вы «крадете» весь исходный код страницы (чтобы сделать его своим и позволить JS получить доступ к DOM), и вы исправляете каждую ссылку / путь в этом источнике, чтобы он также проходит через прокси. Процедура повторного связывания сложна, но выполнима.

Я, наверное, попробую решить эту проблему с перекрестным происхождением, но это в другой день. Наслаждайтесь кодом! :)

не мог найти что-то, что идеально обрабатывало бы большие тексты + большие изображения, но я закончил с этим, кажется, это делает это правильно или почти правильно каждый раз:

    iframe.addEventListener("load",function(){
        // inlineSize, length, perspectiveOrigin, width
        let heightMax = 0;
        // this seems to work best with images...
        heightMax = Math.max(heightMax,iframe.contentWindow.getComputedStyle(iframe.contentWindow.document.body).perspectiveOrigin.split("px")[0]);
        // this seems to work best with text...
        heightMax = Math.max(heightMax,iframe.contentWindow.document.body.scrollHeight);
        // some large 1920x1080 images always gets a little bit off on firefox =/
        const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
        if (isFirefox && heightMax >= 900){
            // grrr..
            heightMax = heightMax + 100;
        }

        iframe.style.height = heightMax+"px";
        //console.info(heightMax);
    });

Другие вопросы по теме