Kirby CMS: Performanteres Einbinden von Youtube-Videos

Ich bin vor Kurzem auf diesen Artikel popup: yes von labnol.org gestoßen, der eine leichtgewichtigere und performantere Lösung beschreibt, um Youtube-Videos zum embedden. Laut labnol werden beim klassischen Embedding fast 500 kb an JavaScript Daten mit mehreren HTTP-Requests geladen, egal ob man sich das Video wirklich anschaut oder nicht. Diesen Prozess kann man umgehen, indem man automatisiert nur das Thumbnail des Videos anzeigt und der Player erst durch einen Klick geladen wird, was die Datenmenge von 500 kb auf ca. 15 kb für das Thumbnail reduziert. Angenehm finde ich an dieser Lösung, dass man mit dem Klick auch direkt das Video gestartet wird, so dass man nicht zweimal auf "Play" klicken muss, wie es bei anderen Lösungen teilweise der Fall ist.

Mit Hilfe der labnol Anleitung hab ich einen eigenen Kirbytag gebaut, mit dem ihr diese Einbindung ganz einfach innerhalb von Kirby nutzen könnt. Kirby stellt ja von Haus aus schon den (youtube) Kirbytag zur Verfügung, der allerdings das klassische Embedding nutzt. Um dies zu ändern will ich natürlich nicht in den Kirby-Core eingreifen, sondern erstelle dafür einen eigenen Tag.

Einen eigenen Kirbytag erstellen

Im Ordner /site/tags erstellt ihr euch eine PHP-Datei mit dem Namen eures Tags. Theoretisch könnte man soweit ich weiß auch den (youtube)-Tag überschreiben, aber ich erstelle in diesem Fall einen neuen, der den Namen youtubelight bekommen soll und nenne die Datei daher entsprechend youtubelight.php. Der Inhalt dieser Datei ist folgender:

<?php

kirbytext::$tags['youtubelight'] = array(
  'html' => function($tag) {
    return '<div class="youtube-player" data-id="' . $tag->attr('youtubelight') . '"></div>';
  }
);

?>

Die erste Zeile sucht quasi im Kirbytext nach einem youtubelight Tag, die zweite und dritte Zeile das dazugehörige HTML. Bei der HTML-Ausgabe greife ich schon auf die Syntax des labnol Tutorials popup: yes zurück:

<div class="youtube-player" data-id="VIDEO_ID"></div>

Über $tag->attr('youtubelight') wird das Attribut des Tags eingesetzt, was dann einfach die benötigte Video-ID enthält. Der Aufbau des Kirbytags ist dann einfach (youtubelight: VIDEOID). Da die Video-ID sowieso bei jedem Youtubelink ersichtlich ist, halte ich diesen Aufbau nicht für umständlich. Man könnte das Ganze natürlich auch so aufbauen, dass man im Tag den kompletten Youtubelink angibt, und sich dann im PHP-Snippet das Attribut so zurechtschneiden, dass nur noch die ID übrigbleibt. Dann könnte man den Tag von der Syntax her analog zum Kirby-eigenen benutzen. Diesen Aufwand hab ich mir aber hier nicht gemacht.

Für weitere Infos zum Thema Kirbytags könnt ihr auch in die Kirby-Docs popup: yes schauen.

Das JavaScript

Als nächstes brauchen wir noch ein bisschen JavaScript, um das zur Video-ID passende Thumbnail zu laden und das Video nach Klick zu starten. Hier kann man das Script von labnol 1:1 anwenden:

<script>

    /* Light YouTube Embeds by @labnol */
    /* Web: http://labnol.org/?p=27941 */

    document.addEventListener("DOMContentLoaded",
        function() {
            var div, n,
                v = document.getElementsByClassName("youtube-player");
            for (n = 0; n < v.length; n++) {
                div = document.createElement("div");
                div.setAttribute("data-id", v[n].dataset.id);
                div.innerHTML = labnolThumb(v[n].dataset.id);
                div.onclick = labnolIframe;
                v[n].appendChild(div);
            }
        });

    function labnolThumb(id) {
        var thumb = '<img src="https://i.ytimg.com/vi/ID/hqdefault.jpg">',
            play = '<div class="play"></div>';
        return thumb.replace("ID", id) + play;
    }

    function labnolIframe() {
        var iframe = document.createElement("iframe");
        var embed = "https://www.youtube.com/embed/ID?autoplay=1";
        iframe.setAttribute("src", embed.replace("ID", this.dataset.id));
        iframe.setAttribute("frameborder", "0");
        iframe.setAttribute("allowfullscreen", "1");
        this.parentNode.replaceChild(iframe, this);
    }

</script>

Styling

Und noch ein bisschen CSS, ebenfalls ohne Änderungen kopiert:

<style>
    .youtube-player {
        position: relative;
        padding-bottom: 56.23%;
        /* Use 75% for 4:3 videos */
        height: 0;
        overflow: hidden;
        max-width: 100%;
        background: #000;
        margin: 5px;
    }

    .youtube-player iframe {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 100;
        background: transparent;
    }

    .youtube-player img {
        bottom: 0;
        display: block;
        left: 0;
        margin: auto;
        max-width: 100%;
        width: 100%;
        position: absolute;
        right: 0;
        top: 0;
        border: none;
        height: auto;
        cursor: pointer;
        -webkit-transition: .4s all;
        -moz-transition: .4s all;
        transition: .4s all;
    }

    .youtube-player img:hover {
        -webkit-filter: brightness(75%);
    }

    .youtube-player .play {
        height: 72px;
        width: 72px;
        left: 50%;
        top: 50%;
        margin-left: -36px;
        margin-top: -36px;
        position: absolute;
        background: url("//i.imgur.com/TxzC70f.png") no-repeat;
        cursor: pointer;
    }

</style>

Und damit ist das Ganze auch schon fertig. Die Grafik des Playbuttons kann man ggf. zur Sicherheit noch selber hosten. Neben der Datenersparnis ist die Tatsache, dass diese Lösung direkt auch responsive funktioniert, ein schöner Nebeneffekt.

Eine konkrete Anwendung des Tags sieht bei mir dann zum Beispiel so aus: (youtubelight: npepWRW7isA).