Responsive iFrames: So bringst du das HTML-Element ins Jahr 2015

Responsive iFrames (Grafik: Shutterstock)
Ein prominentes Beispiel: Youtube-Video responsive einbinden
Der YouTube-iFrame soll folgendermaßen eingebunden werden:
html"><iframe width="560" height="315" src="https://www.youtube.com/embed/9T7eSyo7DRU" frameborder="0" allowfullscreen></iframe>
Die Breite des iFrames überschreibt man durch CSS wie auch bei Responsive Images:
img,
iframe {
max-width: 100%;
}
Die Breite passt sich immer dem Container an. Die Höhe wird leider nicht automatisch angepasst – im Beispiel bleibt die Höhe also bei 315 Pixel. Die Regel height: auto;
hat hier leider keinen Einfluss auf unseren iFrame. Das Problem bleibt die relationale Höhenanpassung des iFrames, wenn sich die Breite verändert.
Für das reponsive iFrame-Video behelfen wir uns mit einem bekannten Trick. Den iFrame umschließen wir mit einem Container-DIV und erweitern den Container mit padding-bottom
durch die prozentuale Höhe des Seitenverhältnisses des iFrames, genauso wie bei Lazy Loading.
Beispiel:
<div class="embed-container"><iframe width="560" height="315" src="https://www.youtube.com/embed/9T7eSyo7DRU" frameborder="0" allowfullscreen></iframe>>/div>
.embed-container {
position: relative;
padding-bottom: 56.25%; /* ratio 16x9 */
height: 0;
overflow: hidden;
width: 100%;
height: auto;
}
.embed-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* ratio 4x3 */
.embed-container.ratio4x3 {
padding-bottom: 75%;
}
Jetzt wird die Video-Containerhöhe immer relational an die Breite angepasst. Je nach Seitenverhältnis kann man auch weitere Klassen im .embed-container
verwenden, beispielsweise .ratio4x3
für ein Seitenverhälnis 4:3.
Bei einem externen Video mit festem Seitenverhältnis ist das recht einfach, schwieriger wird es mit interaktiven Inhalten, die eine dynamische Höhe haben.
iFrame-Interaktion
Wenn man im iFrame weitere Aktionen durchführen kann (Bestellformulare zum Beispiel) und die iFrame-Inhaltsseiten unterschiedlich lang sind, wird unter Umständen ein Scrollbalken angezeigt – oder man hat viel Weißraum. Dieses Verhalten ist verständlicherweise nicht gewollt. In einem Projekt sollte die Anwendung (Berechnung einer Versicherung) in Partnerwebseiten eingebunden werden, ohne dass auffällt, dass es eine externe Anwendung (ein externes Produkt) ist.
Das ist unlängst komplizierter, da iFrames insbesondere von verschiedenen Domains aus Sicherheitsgründen nicht so einfach miteinander kommunizieren dürfen (Same-Origin-Policy).
Same-Origin-iFrame
Wenn der iFrame von der gleichen Domain aus beispielsweise mit der ID „responsive-iframe“ eingebunden ist, kann man folgende jQuery-Funktion verwenden.
$(function(){
$(window).on('load resize', adjustIframe);
});
function adjustIframe() {
$(parent.document.getElementById("responsive-iframe")).css("height", $("html").css("height"));
}
Erfolgt die Einbindung unter einer anderen Domain muss man eine andere Technik verwenden, damit die Kommunikation zwischen den Frames gewährleistet ist.
Cross-Origin-iFrame
In HTML5 ist postMessage
eingeführt worden, das eine Kommunikation zwischen Browserfenstern erlaubt. Hiermit ist es möglich, die aktuelle Höhe des iFrame-Inhalts an die einbindende Seite zu übermitteln.
postMessage-Definition:
otherWindow.postMessage(message, targetOrigin, [transfer]);
JavaScript-Funktion für Cross-Origin-responsive-iFrames
iframe.html – Sender:
var rIframe = {};
rIframe.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
rIframe.windowHeight = 0;
rIframe.htmlElement = document.getElementsByTagName('html')[0];
rIframe.targetDomain = 'domain.tld';
rIframe.resizeFrame = function (){
var windowHeight = document.body ? Math.max(document.body.offsetHeight, rIframe.htmlElement.offsetHeight) : rIframe.htmlElement.offsetHeight ;
if ( rIframe.windowHeight === windowHeight ) {
rIframe.requestAnimFrame.call(window, rIframe.resizeFrame);
return false;
}
rIframe.windowHeight = windowHeight;
try {
// Same Origin iFrame
window.frameElement.style.height = windowHeight + 'px';
}
catch ( e ) {
// Cross Origin iFrame
window.parent.postMessage('resize:' + windowHeight , rIframe.targetDomain);
}
rIframe.requestAnimFrame.call(window, rIframe.resizeFrame);
};
rIframe.requestAnimFrame.call(window, rIframe.resizeFrame);
index.html – Empfänger:
function receiveMessage(event) {
var message = event.data.split(':');
var eventName = message[0];
var iframes, len, i = 0;
// only receive messages from this domain
var senderDomains = ['domain.tld'];
if ( senderDomains.indexOf(event.origin) !== -1 && eventName === 'resize' ) {
iframes = document.getElementsByTagName('iframe');
len = iframes.length;
for (; i < len; i++) {
if ( ( iframes[i].contentWindow || iframes[i].documentWindow ) == event.source) {
iframes[i].style.height = message[1] + "px";
return;
}
}
}
}
if ( window.addEventListener ) {
window.addEventListener('message', receiveMessage, false);
}
else if (window.attachEvent) {
window.attachEvent('onmessage', receiveMessage);
}
Den kompletten Code findet ihr hier.
JavaScript-Plugins
easyXMD
easyXDM ist eine Javascript-Library, die es Entwicklern ermöglicht, mit den Limitierung der Same-Origin-Policy umzugehen und Anwendungen Cross-Domain kommunizieren zu lassen. Im Blogpost auf easyxdm.net wird gut beschrieben, welche Schritte man unternehmen muss.
Wer im Projekt jQuery verwendet, kann das „responsiveiframe“-Plugin von NPR verwenden. Eine umfangreiche API für iFrame-Embeds bietet iframely. Die Basisvariante ist auch auf Github verfügbar. Der Online-Service bietet noch weitere Features, wenn man ein Bezahlmodell wählt.
iFrames: Performance-Tweak
Ein letzter Hinweis: Wenn der iFrame onload nicht im Viewport ist, sollte man überlegen, ob man den iFrame mit einer Lazy-Loading-Technik verzögert lädt. Am Beispiel der lazySizes-Bibliothek von Alex Farkas ist das sehr einfach zu integrieren.
<iframe data-src="//www.youtube.com/embed/ZfV-aYdU4uE" class="lazyload" frameborder="0" allowfullscreen></iframe>
Die eigentliche Soure (src) wird durch „data-src“ ersetzt und zusätzlich mit der Klasse „lazyload“ versehen. Das Script lädt dann den iFrame beim Scrollen nach, wenn der iFrame sich dem Viewport nähert.
Das ist aber mehr oder weniger nur ein Zusatzfeature der Bibliothek – das Hauptaugenmerk liegt auf dem Lazy-Loading von Responsive Images (srcset/picture). Also durchaus ein Script, das man in vielerlei Hinsicht verwenden kann.
Dieser Artikel erschien zuerst auf maddesigns.de.
ReSponsive iFrames ;)
Endlich iFrames im responsive Style!!!
>/div>
Da ist eine Klammer falsch …
Sonst guter Artikel!