Das könnte dich auch interessieren

Du hast deinen AdBlocker an?

Es wäre ein Traum, wenn du ihn für t3n.de deaktivierst. Wir zeigen dir gerne, wie das geht. Und natürlich erklären wir dir auch, warum uns das so wichtig ist. Digitales High-five, deine t3n-Redaktion

Entwicklung

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

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

Responsive iFrames (Grafik: Shutterstock)

Responsive iFrames? Das klingt schon falsch – und ist auch ein schwieriges Pflaster. Grundsätzlich können iFrames responsiv sein, Voraussetzung ist natürlich, dass sich ihr Inhalt ebenfalls responsiv verhält. Es ist ja quasi ein Browserfenster im Browserfenster. Doch die Anpassung der Breite ist nicht das Problem, die Anpassung der Höhe macht es kompliziert.

Ein prominentes Beispiel: Youtube-Video responsive einbinden

Der YouTube-iFrame soll folgendermaßen eingebunden werden:

<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.

Finde einen Job, den du liebst zum Thema Webdesign, Webentwickler

3 Reaktionen
Nikolaus
Nikolaus

>/div>
Da ist eine Klammer falsch ...

Sonst guter Artikel!

Antworten

Markus
Markus

Endlich iFrames im responsive Style!!!

Antworten

Sven
Sven

ReSponsive iFrames ;)

Antworten

Melde dich mit deinem t3n-Account an oder fülle die unteren Felder aus.

Abbrechen