Улучшение работы iframe

Скромный <iframe> — это полезный способ представления содержимого другой веб-страницы, но его бывает довольно сложно заставить работать без проблем. В этой небольшой статье представлен способ сделать их немного проще для интеграции в отзывчивый дизайн.

Настройка iframe

Добавить вложенный контент очень просто — достаточно добавить тег <iframe> с атрибутом src, указывающим на контент, который необходимо включить.

<iframe src="/nested-content.html"></iframe>
Вход в полноэкранный режим Выход из полноэкранного режима

Из коробки это оставляет желать лучшего — в частности, высота и ширина не учитывают размер главной страницы или вложенного содержимого!

Ширину довольно легко исправить, установив ширину элемента iframe равной 100%. Самый быстрый способ сделать это — установить размер по умолчанию.

iframe { width: 100%; }
Вход в полноэкранный режим Выход из полноэкранного режима

Какова высота этого iframe?

Высота — это немного другой вопрос. Хотя высоту можно задать тем же способом (или через атрибут iframe), возникает вопрос, насколько большой она должна быть. В идеале мы должны задать высоту содержимого iframe, но нет надежного способа узнать это. Для простой вложенной страницы это довольно просто.

#nested-content { height: 5.5rem; }
Вход в полноэкранный режим Выйдите из полноэкранного режима

Это выглядит намного лучше! Однако есть проблема: это фиксированная высота, поэтому содержимое не будет реагировать на изменения размера экрана или содержимого вложенной страницы. Если содержимое длиннее, чем заданный размер, мы получим полосу прокрутки в iframe, что может оказаться не тем, что нам нужно.

Сделать высоту отзывчивой

Хорошая новость заключается в том, что мы можем добиться такого динамического изменения размера, используя тривиальный объем JavaScript! Из-за ограничений, введенных CORS (Cross-Origin Resource Sharing) для предотвращения атак, мы должны использовать метод postMessage() для безопасного обмена информацией между родительской и вложенной страницей.

Основной процесс заключается в вычислении размера вложенной страницы с помощью метода getBoundingClientRect() элемента верхнего уровня вложенной страницы. Он доступен с помощью document.documentElement. Затем мы сообщаем родительской странице новую высоту. Слушатель событий делает это реакцией на изменение высоты страницы.

function sendResizeMessage() {
  const height = document.documentElement
    .getBoundingClientRect().height;
  parent.postMessage({ height }, parent.location);
}
sendResizeMessage();
addEventListener('resize', sendResizeMessage);
Вход в полноэкранный режим Выход из полноэкранного режима

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

const iframe = document.getElementById('iframe-id');
addEventListener('message', (event) => {
  const height = event.data.height;
  iframe.style.height = height + 'px';
});
Вход в полноэкранный режим Выход из полноэкранного режима

Как хорошие граждане, они оба загружаются в обработчиках DOMContentLoaded.

addEventListener(
  'DOMContentLoaded',
  <initialisation code here!>
);
Вход в полноэкранный режим Выход из полноэкранного режима

Повышение безопасности

Хотя код, который мы запускаем, достаточно безобиден, существует вероятность того, что кто-то может написать нам сообщение и установить высоту iframe. В документации postMessage() предлагается подтвердить личность отправителя, проверив источник и происхождение события.

Обновленный слушатель сообщений теперь выглядит следующим образом:

const iframe = document.getElementById('iframe-id');
addEventListener('message', (event) => {
  if(!(
    event.source === iframe.contentWindow &&
    event.origin === 'https://example.com'
  )) return;

  const height = event.data.height;
  iframe.style.height = height + 'px';
});
Вход в полноэкранный режим Выход из полноэкранного режима

Все, что мы здесь сделали, это проверили, что

  • источником события является окно содержимого iframe
  • источником события является ожидаемый url

Обратите внимание, что это отрицание, так что если они не совпадают, функция возвращается раньше.

В репозитории iframe-resizer на GitHub я привел более подробный пример, и вы можете увидеть его в действии.

Надеюсь, это было полезно, и спасибо за чтение!

Оцените статью
Procodings.ru
Добавить комментарий