← Назад к вопросам

Есть ли DOM в iframe?

2.2 Middle🔥 144 комментариев
#JavaScript Core

Комментарии (4)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

DOM в iframe

Да, внутри iframe полностью присутствует собственный DOM. Каждый iframe является отдельным контекстом документа с собственным window объектом, document объектом и полной иерархией DOM элементов. Это - важное понимание при работе с iframe'ами в веб-приложениях, так как доступ к содержимому iframe требует особых методов и имеет определённые ограничения безопасности.

Структура iframe

iframe содержит полный HTML документ внутри себя:

<!-- Родительская страница -->
<html>
<head>
  <title>Основная страница</title>
</head>
<body>
  <h1>Родительский контент</h1>
  
  <!-- iframe с собственным DOM -->
  <iframe id="myFrame" src="./embedded.html"></iframe>
</body>
</html>

Доступ к DOM элементам внутри iframe

1. Доступ к содержимому iframe из родителя

// Получить элемент iframe
const iframe = document.getElementById('myFrame')

// Получить window объект iframe
const iframeWindow = iframe.contentWindow

// Получить document объект iframe
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document

// Получить элемент внутри iframe
const iframeElement = iframeDocument.getElementById('elementInIframe')

// Изменить стили элемента внутри iframe
if (iframeElement) {
  iframeElement.style.color = 'red'
}

2. Доступ из iframe к родительскому документу

// Внутри iframe

// Получить window родителя
const parentWindow = window.parent

// Получить document родителя
const parentDocument = window.parent.document

// Получить элемент в родителе
const parentElement = parentWindow.document.getElementById('parentId')

// Обратиться к top-level window (для вложенных iframe)
const topWindow = window.top

// Проверить, находимся ли мы внутри iframe
const isInIframe = window.self !== window.top

if (isInIframe) {
  console.log('Мы внутри iframe')
  parentWindow.console.log('Сообщение в родителя')
}

Практический пример: Работа с iframe в React

function IframeWrapper({ children }) {
  const iframeRef = useRef(null)
  const [iframeDoc, setIframeDoc] = useState(null)
  
  useEffect(() => {
    const iframe = iframeRef.current
    if (!iframe) return
    
    const handleLoad = () => {
      const doc = iframe.contentDocument || iframe.contentWindow.document
      setIframeDoc(doc)
    }
    
    iframe.addEventListener('load', handleLoad)
    return () => iframe.removeEventListener('load', handleLoad)
  }, [])
  
  useEffect(() => {
    if (!iframeDoc) return
    
    iframeDoc.open()
    iframeDoc.write(`
      <!DOCTYPE html>
      <html>
      <head>
        <style>
          body { font-family: Arial; margin: 0; padding: 10px; }
          .content { background: #f0f0f0; padding: 10px; border-radius: 4px; }
        </style>
      </head>
      <body>
        <div class="content">${children}</div>
      </body>
      </html>
    `)
    iframeDoc.close()
  }, [iframeDoc, children])
  
  return <iframe ref={iframeRef} style={{ width: '100%', height: '300px' }} />
}

CORS и безопасность

Доступ к iframe ограничен политикой Same-Origin Policy:

// Если iframe с другого домена - доступ будет заблокирован
const iframe = document.getElementById('cross-origin-frame')

try {
  // Это вызовет SecurityError для cross-origin iframe
  const doc = iframe.contentDocument
  console.log(doc) // null для cross-origin
} catch (e) {
  console.error('Доступ запрещён (cross-origin iframe)')
}

// Для cross-origin communication используйте postMessage
iframe.contentWindow.postMessage(
  { message: 'Hello from parent' },
  'https://example.com'
)

// Слушать ответ из iframe
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://example.com') return
  console.log('Сообщение из iframe:', event.data)
})

postMessage для cross-origin iframe

Универсальный способ общения, работающий для любых origin:

// Родитель отправляет сообщение в iframe
function sendMessageToIframe(message) {
  const iframe = document.getElementById('myFrame')
  iframe.contentWindow.postMessage(
    { type: 'PARENT_MESSAGE', payload: message },
    '*'
  )
}

// Родитель слушает сообщения из iframe
window.addEventListener('message', (event) => {
  console.log('Получено из iframe:', event.data)
  console.log('От origin:', event.origin)
})

// Внутри iframe отправляет обратно
window.parent.postMessage(
  { type: 'IFRAME_RESPONSE', data: 'Ответ из iframe' },
  '*'
)

Особенности и ограничения

  1. Same-Origin Policy - cross-origin iframe доступны только через postMessage
  2. Производительность - каждый iframe создаёт новый браузерный контекст
  3. Стили - стили родителя не наследуются в iframe (нужно добавлять отдельно)
  4. Шрифты - шрифты нужно подгружать заново внутри iframe
  5. JavaScript контекст - код в iframe выполняется в отдельном контексте
Есть ли DOM в iframe? | PrepBro