Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи? Написать
Дайджесты новостей
Сравнение подходов к адаптивным iframe: слева устаревшая модель с двойной прокруткой и скриптовыми обертками, справа нативное свойство frame-sizing с автоматическим подбором высоты и двусторонним согласованием

Адаптивные iframe в Chrome 154: нативное свойство frame-sizing взамен костылей с postMessage

Встраивание сторонних интерактивных компонентов — виджетов комментариев, платежных форм, опросов или постов из социальных сетей — на протяжении десятилетий оставалось одной из самых болезненных тем веб-разработки. Традиционный элемент <iframe> обладает собственной изолированной областью просмотра с фиксированными размерами. Если контент внутри оказывается выше окна фрейма, появляется уродливая двойная полоса прокрутки; если контент уменьшается, на странице зияет пустое белое пространство.

Чтобы обойти это, разработчики городили громоздкие скрипты: встроенный документ с помощью ResizeObserver замерял высоту страницы и через window.postMessage пересылал ее родительскому окну, где JavaScript динамически переписывал CSS-стили контейнера. В Chrome 154 и актуальных сборках Edge за экспериментальными флагами появилась долгожданная альтернатива — нативная спецификация адаптивного масштабирования фреймов (Responsive iframes) на базе CSS-свойства frame-sizing.

Нативное свойство frame-sizing и двустороннее согласие

Новая спецификация переносит вычисление высоты фрейма непосредственно в компоновочный движок браузера. На стороне родительской страницы разработчику достаточно указать CSS-свойство frame-sizing: content-height:

/* Родительская страница: фрейм автоматически растет под свой контент */
.embedded-widget {
  width: 100%;
  max-height: 85vh; /* Защита от бесконечного растягивания */
  border: none;
  frame-sizing: content-height;
}

Однако произвольное растягивание стороннего сайта наружу несет серьезные риски атак кликджекинга и переполнения макета. Поэтому спецификация требует строгого двустороннего согласия (Opt-In). Документ, загружаемый внутри фрейма, обязан явно подтвердить готовность предоставить свои истинные размеры через специальный метатег в секции <head>:

<!-- Встраиваемый документ: подтверждение передачи размеров -->
<!doctype html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <!-- Разрешение адаптивного размера для доверенных источников -->
  <meta name="responsive-embedded-sizing" content="allow-origins=https://example.com https://partner.org">
  <title>Виджет обсуждения</title>
</head>
<body>
  <div id="comments-container">
    <!-- Интерактивный контент виджета -->
  </div>
</body>
</html>

Если метатег отсутствует или источник родительской страницы не входит в разрешенный перечень allow-origins, браузер игнорирует frame-sizing, и фрейм сохраняет фиксированные стандартные размеры. Метатег нельзя внедрять динамически через JavaScript после первичного рендеринга страницы — браузер считывает его строго на этапе первичного разбора HTML.

Динамические изменения и метод window.requestResize()

Браузер вычисляет высоту содержимого встроенного документа при первой загрузке, но не отслеживает непрерывно каждую микроперерисовку внутри чужого контекста, чтобы не допускать просадок производительности. Если контент фрейма изменился в результате асинхронного действия пользователя — например, подгрузилась следующая страница комментариев, раскрылся аккордеон или развернулась форма ответа — встроенный документ запрашивает новый расчет геометрии через новый интерфейс:

// Внутри встроенного фрейма: пересчет после асинхронной подгрузки
async function loadMoreComments() {
  const response = await fetch('/api/comments?page=2');
  const comments = await response.json();
  
  renderComments(comments);
  
  // Явный запрос к браузеру на пересчет высоты родительского iframe
  if (typeof window.requestResize === 'function') {
    window.requestResize();
  }
}

Вызов window.requestResize() инициирует проверку высоты контейнера в следующем кадре отрисовки без накладных расходов на передачу сериализованных сообщений между окнами.

Защита от сдвигов макета (CLS) и прогрессивное улучшение

Главный архитектурный компромисс адаптивных фреймов связан с метриками пользовательского опыта, в первую очередь Cumulative Layout Shift (CLS). Поскольку встроенный документ почти всегда загружается медленнее родительского HTML-каркаса, внезапное изменение высоты с 0 до 800 пикселей может сдвинуть весь основной текст страницы вниз, ухудшая показатели Core Web Vitals.

Для минимизации скачков рекомендуется:

  1. Задавать для .embedded-widget ожидаемую начальную высоту через min-height или свойство aspect-ratio.
  2. Не размещать адаптивные фреймы на первом экране просмотра (above the fold).
  3. Ограничивать вертикальный рост свойством max-height со включенным внутренним overflow-y: auto.

Пока спецификация находится на этапе тестирования, команды могут применять прогрессивное улучшение через @supports (frame-sizing: content-height), сохраняя проверенный fallback на postMessage для старых браузеров.