Introduzione
Un iframe permette di visualizzare un documento HTML all’interno di un’altra pagina web. Oltre a incorporare contenuti, però, è importante gestire due problemi molto comuni: l’adattamento alle diverse dimensioni dello schermo e la comunicazione tra la pagina principale e il documento incorporato.
Un iframe con larghezza o altezza fisse può creare barre di scorrimento indesiderate su smartphone. Inoltre, la pagina contenuta nell’iframe è un documento separato: per impostazione predefinita non può interagire liberamente con la pagina che lo ospita, soprattutto quando i due documenti appartengono a origini diverse.
In questo tutorial realizzeremo un esempio pratico composto da una pagina principale e da un contenuto incorporato. L’iframe sarà responsive, avrà un rapporto d’aspetto proporzionale e riceverà messaggi tramite l’API postMessage. Questa tecnica è utile per aggiornare un widget, ridimensionare un’area incorporata o notificare alla pagina principale un’azione eseguita nel documento interno.
Codice completo
Il seguente esempio mostra una pagina principale con un iframe responsive. Il contenitore mantiene un rapporto di 16:9 grazie alla proprietà CSS aspect-ratio. L’attributo title migliora l’accessibilità, mentre loading="lazy" rimanda il caricamento finché l’iframe non si avvicina all’area visibile.
<section class="embedded-content">
<h2>Widget incorporato</h2>
<div class="iframe-wrapper">
<iframe
id="demo-frame"
src="widget.html"
title="Widget dimostrativo incorporato"
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin">
</iframe>
</div>
<p id="status" role="status">
In attesa di un messaggio dal widget...
</p>
</section>
<style>
.iframe-wrapper {
width: 100%;
max-width: 960px;
aspect-ratio: 16 / 9;
overflow: hidden;
border: 1px solid #cbd5e1;
border-radius: 12px;
background: #f8fafc;
}
.iframe-wrapper iframe {
width: 100%;
height: 100%;
border: 0;
display: block;
}
</style>
<script>
const frame = document.querySelector(´#demo-frame´);
const status = document.querySelector(´#status´);
window.addEventListener(´message´, (event) => {
// Verifica sempre l´origine del documento mittente.
if (event.origin !== window.location.origin) {
return;
}
// Accetta soltanto il formato di messaggio previsto.
if (event.data?.type === ´widget-ready´) {
status.textContent = ´Il widget è pronto e comunica correttamente.´;
}
});
</script> Il file widget.html, caricato dentro l’iframe, può inviare una notifica alla pagina principale nel momento in cui è pronto:
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<title>Widget</title>
</head>
<body>
<button id="notify-button">Invia notifica</button>
<script>
const parentOrigin = window.location.origin;
window.parent.postMessage(
{ type: ´widget-ready´ },
parentOrigin
);
document.querySelector(´#notify-button´).addEventListener(´click´, () => {
window.parent.postMessage(
{ type: ´widget-button-clicked´ },
parentOrigin
);
});
</script>
</body>
</html> Spiegazione
Adattare l’iframe allo spazio disponibile
Il wrapper usa width: 100% per occupare la larghezza disponibile e max-width per evitare che il contenuto diventi eccessivamente largo su monitor grandi. La proprietà aspect-ratio: 16 / 9 mantiene proporzionata l’altezza senza ricorrere a calcoli JavaScript.
L’iframe eredita la dimensione del contenitore tramite width: 100% e height: 100%. L’impostazione display: block elimina il piccolo spazio verticale che alcuni browser possono visualizzare sotto gli elementi inline.
Comunicare con postMessage
La funzione window.parent.postMessage() consente al documento dentro l’iframe di inviare dati alla pagina che lo contiene. Il primo argomento è il messaggio, spesso rappresentato da un oggetto con una proprietà type. Il secondo argomento indica l’origine autorizzata del destinatario.
La pagina principale ascolta questi messaggi con l’evento message. Non bisogna accettare qualsiasi messaggio ricevuto: il controllo di event.origin è essenziale per verificare da quale origine proviene la comunicazione. È inoltre consigliabile validare la struttura di event.data, invece di usare direttamente valori ricevuti dall’esterno.
Origine e stessa origine
Due documenti appartengono alla stessa origine quando condividono protocollo, dominio e porta. Un iframe caricato da un dominio differente non può accedere direttamente al DOM della pagina principale. postMessage rappresenta il canale corretto per comunicare in modo controllato tra documenti separati.
Best practice
- Imposta sempre un attributo title descrittivo, così gli utenti che utilizzano lettori di schermo comprendono il contenuto dell’iframe.
- Preferisci un contenitore responsive con aspect-ratio invece di valori rigidi come width="800" e height="600".
- Usa loading="lazy" per iframe non immediatamente visibili, soprattutto quando una pagina contiene molti contenuti incorporati.
- Controlla sempre event.origin prima di elaborare un messaggio ricevuto tramite postMessage.
- Invia i messaggi a un’origine precisa, evitando il valore jolly "*" quando conosci già il dominio destinatario.
- Definisci un formato chiaro per i messaggi, ad esempio un oggetto con una proprietà type e altri dati esplicitamente documentati.
- Non inserire nel DOM dati ricevuti dall’iframe tramite innerHTML senza una corretta sanitizzazione.
- Usa referrerpolicy per limitare le informazioni sull’URL della pagina principale inviate durante il caricamento del contenuto.
- Prova l’interfaccia su smartphone, tablet e monitor larghi, verificando anche orientamento verticale e orizzontale.
Riepilogo
Un iframe ben progettato non deve limitarsi a mostrare un documento: deve integrarsi correttamente con il layout e con il comportamento della pagina ospitante. Il pattern con contenitore responsive e aspect-ratio consente di mantenere proporzioni coerenti su dispositivi diversi.
Quando è necessario scambiare informazioni, postMessage offre un meccanismo standard tra documenti. La sicurezza dipende dalla verifica dell’origine e dalla validazione dei dati ricevuti. Combinando responsive design, accessibilità, caricamento differito e comunicazione controllata, è possibile creare integrazioni più affidabili e professionali.
