HTML5 Iframe-Attribut seamless schon jetzt nutzen (Alle Informationen und Beispiele)

Es gibt sie auf fast jeder Internetseite und trotzdem mag sie kein Webentwickler: Iframes. Früher wurden sie verwendet um ganze Internet-Auftritte umzusetzen (Stichwort: nav.html, content.html), heute Fristen sie ein unscheinbares Dasein als Container-Elemente unzähliger Social-Media- und Werbe-Boxen. Das Arbeiten mit Iframes wird jedoch durch HTML5 bald um einiges angenehmer werden. Welche Vorteile das hat, wie man die Features teilweise schon jetzt nutzen kann und warum Iframes gar nicht so böse sind, erklärte Ben Vinegar vor einiger Zeit in einem Vortrag. Die Slides dazu gibt es hier, die eingedeutschte Zusammenfassung mit Beispielen in diesem Artikel.

Keine Zeit? Hier geht’s direkt zur Demo-Seite inkl. Code.

Sind Iframes wirklich böse? Nein!

seamless-Iframe Attribut schon jetzt nutzen
Das seamless-Attribut und seine Möglichkeiten

Iframes, also quasi Webseiten in Webseiten, sind vom Rest der Seite isoliert, bilden eine sogenannte Sandbox. Das hat Nachteile für Webentwickler: CSS wird nicht in den Frame übernommen, Links innerhalb des Iframes verweisen nicht auf die einbindende Seite und die Größe des Frame-Elements passt sich nicht an den Inhalt darin an. Doch genau dieses Sandbox-Prinzip hat Vorteile: JavaScript-Konflikte werden verhindert und Sicherheit und Datenschutz des Users gewahrt. Services wie Flattr, Google Adsense und viele Andere können und müssen via Iframe in die eigene Seite eingebunden werden.

HTML5 und das seamless-Attribut

Da derzeitige Nachteile nicht zukünftig das Arbeiten mit Iframes verhindern sollen, wurde das HTML5-Attribut seamless hinzugefügt. Ein einfaches Beispiel:

[html]<iframe seamless src="http://www.solife.cc"></iframe>[/html]

CSS-Eigenschaften werden dadurch direkt in den Frame übernommen und die Links öffnen korrekt im übergeordneten Fenster. Außerdem passt sich der Iframe mit dem Attribut der Höhe des Inhalts an und Linien sowie Scrollbalken werden standardmässig nicht angezeigt. Wie bei allen neuen Errungenschaften im Web gibt es Dinge zu beachten und Kompromisse einzugehen:

  • Es wird nur http://, nicht aber file:// unterstützt
  • Kein einziger Stable-Browser verfügt derzeit über Support
  • Nur Google Chrome Canary (Version 22 und höher) unterstüzt derzeit das Attribut
  • Die Implementierung der anderen Browser kann als oberflächlich bezeichnet werden

Schon jetzt die neuen Vorteile nutzen

Um schon jetzt die Vorteile des seamless-Attributes zu Nutzen bedarf es einiger Tricks. Zu aller erst muss sowohl auf der Hauptseite, als auch im Iframe selbst, JavaScript-Code eingefügt werden. Damit beide Bereiche kommunizieren können, wird die window.postMessage-Methode genutzt. Die Optik der “nahtlosen” Darstellung kann mit etwas CSS nachgebaut werden.

Einrichten von postMessage und CSS

Code der Hauptseite:

[js]<iframe seamless id="myFrame" src="iframe.html"></iframe>


<script>
var iframe = document.getElementById("myFrame");
// Erste Test-Nachricht an den Iframe
iframe.onload = function() {
iframe.contentWindow.postMessage(‚Hallo Iframe!‘, "*" );
};
</script>[/js]

Da die Nachricht erst gesendet werden soll, wenn der Iframe schon geladen ist, verwende ich den onload-Event-Handler.

JavaScript-Code für den Iframe:

[js] // Wird aufgerufen bei einer neuen Nachricht
function listener(e){
alert(e.data);
}

// Listener für alle Browser
if (window.addEventListener){
window.addEventListener("message", listener, false);
} else {
window.attachEvent("onmessage", listener);
}
[/js]
Wir haben nun die erste Test-Nachricht via Hauptseite an den Iframe gesendet. Die Vorteile von postMessage können wir nun nutzen, um unterschiedliche Werte an den Frame zu übermitteln und das seamless-Attribut teilweise zu simulieren.

CSS für die Hauptseite (Nahtloser Iframe-Effekt):

[css]iframe[seamless]{
background-color: transparent;
border: 0 none transparent;
padding: 0;
overflow: hidden;
}[/css]

Um Links innerhalb des Iframes korrekt zu öffnen, könnte man bei jedem Link das Attribut target="_parent" hinzufügen. Das ist allerdings Wartungsintensiv und überladet das Markup. Dank des <base>-Tags und etwas Java-Script kann dies automatisiert werden.

Im <head>-Bereich des Iframes einfügen:

[html]<base href="http://www.solife.cc/" target="_parent">[/html]

Die angegebene URL des href-Attributes ist nicht zwingend notwendig, da sie mittels Javascript gleich mit der dynamischen Seiten-URL getauscht wird.

Im JavaScript (onLoad-Bereich) der Hauptseite einfügen:

[js] // Schicke aktuelle URL an Iframe
iframe.contentWindow.postMessage([‚referrer‘, window.location.href], ‚*‘);
[/js]

Javascript des Iframes empfängt Nachricht und ändert Base-URL:

[js] // Neue Listener-Funktion
function listener(e){

var eventName = e.data[0],
data = e.data[1];

switch (eventName) {
case ‚referrer': setNewBase(data); break;
}

}

// Aktualisiere Base-URL
function setNewBase(url) {
document.getElementsByTagName(‚base‘)[0].href = url;
}
[/js]

Styles in den Iframe übernehmen

Es ist keine perfekte Lösung, aber es können beliebige Style-Eigenschaften wie Schriftart, Schriftgröße und Schriftfarbe via Nachricht dem Iframe übergeben werden. In diesem Beispiel wird dies Mithilfe von jQuery gelöst:

[js] iframe.onload = function() {

….
// Style-Eigenschaften an Iframe senden
iframe.contentWindow.postMessage([‚styles‘, getIframeStyles(iframe)], ‚*‘);

};

// Styles auslesen (Dazu wird ein leeres span-Element erstellt)
function getIframeStyles(iframe) {

var $span = $(‚<span>‘).appendTo(iframe.parentNode);

var styles = {
color: $span.css(‚color‘),
fontFamily: $span.css(‚font-family‘),
fontSize: $span.css(‚font-size‘)
};

$span.remove(); // Cleanup
return styles;

}
[/js]

Natürlich können beliebig viele Styles an den Iframe übergeben werden. Auch ist es möglich ganze CSS-File-URL’s zu versenden, um sie später einzufügen. Wir bleiben bei der einfachen Methode der Werte-Übermittlung.

Beim Iframe selbst nun folgenden Code einfügen:

[js]function listener(e){

….

switch (eventName) {
case ‚referrer': setNewBase(data); break;
case ‚styles': injectStyles(data); break;
}

}

function injectStyles(styles) {
$(document.body).css(styles);
}
[/js]
Wie oben beschrieben gibt es viele Wege die gewünschten Style-Eigenschaften in den Frame zu bekommen. Dem Webworker ist überlassen wie er diesen Prozess umsetzt.

Höhe des Iframes automatisch anpassen

Jeder Coder der bereits einmal ein Gästebuch oder ähnliches via Iframe einbinden musste, kennt das Problem: Welche Höhe definiert man dem Iframe-Element? Gerade bei dynamischen Seiten ist diese Frage schwer zu beantworten – die Lösung ist meist eine Höhe von weit über 1000 Pixel zu wählen. Dank postMessage kann die korrekte Höhe nun direkt übertragen werden.

Da in diesem Schritt die Hauptseite, nicht wie bisher, Nachrichten sendet, sondern auch empfängt, muss ein ähnlicher Code wie im Iframe eingebunden werden.
[js] // Wird aufgerufen bei einer neuen Nachricht
// Auf Hauptseite nur um Höhe anzupassen
function listener(e){

var eventName = e.data[0],
data = e.data[1];

switch (eventName) {
case ‚setHeight': $(iframe).height(data); break;
}

}

// Listener für alle Browser
if (window.addEventListener){
window.addEventListener("message", listener, false);
} else {
window.attachEvent("onmessage", listener);
}
[/js]

Das JavaScript des Iframes aktualisieren:
[js] // Resize-Funktion zum Ermitteln der Höhe
function resize() {
window.parent.postMessage([‚setHeight‘, $(‚html‘).height()], ‚*‘);
}
[/js]
Jetzt muss die resize()-Funktion nur noch aufgerufen werden. Auch hier gibt es mehrere Möglichkeiten der Umsetzung:

  • Die Funktion wird permanent via Interval alle 500 Millisekunden odgl. aufgerufen
  • Die Funktion feuert erst wenn ein bestimmtes Event eingetreten ist
  • Wie Ben Vinegar in seinem Vortrag, mit der Debounce-Methode (Code)

Zur einfacheren Vorstellung verwende ich für dieses Beispiel die Interval-Methode.
[js] // Alle 500 Millisekunden die Höhe des Frames anpassen
window.setInterval(resize, 500);
[/js]
Das Iframe passt sich nun immer der Höhe des Inhalts darin an.

Resume

Mit diesen wenigen Code-Zeilen ist es möglich das Arbeiten mit Iframes erheblich zu verbessern und das seamless-Attribut zumindest teilweise nachzubauen. Die window.postMessage-Methode wird in allen Browser, bis auf Internet Explorer 6 und 7 unterstützt. Bis alle Browser nachgerüstet haben bleibt dieser Workflow eine passable Alternative.

Zur Demo-Seite inkl. Code.