Die Eintragsvorschau in Serendipity

Die meisten Content-Management- und Blog-Systeme bieten eine Möglichkeit, sich vor dem Veröffentlichen einer Seite oder eines Artikels eine Vorschau davon anzeigen zu lassen. Das ist ein wenig ein Relikt aus dem vorresponsiven Zeitalter, als es nur genau eine Ansicht einer Website gab (und die war meistens „optimiert für 1024×768 Pixel“ und/oder irgendeine bestimmte Version eines Browsers). Das liegt auch daran, dass man Inhalte meistens in einem WYSIWYG-Editor verfasst, der keine Live-Vorschau bietet – man möchte ja keine fehlerhaften Texte publizieren.

So eine Vorschau bietet auch Serendipity, und zu meinem großen, langjährigen Leidwesen wird sie in einem <iframe> erzeugt. Ich glaube, Garvin hat mir schon mehrmals erklären müssen, warum das mal so gemacht wurde und weshalb es jetzt nicht einfach so geändert werden kann, ich kann es mir aber nicht merken. Es spielt auch keine Rolle, irgendwie gäbe es auch keine wirklich bessere Lösung. Es ist ohnehin nur problematisch, weil <iframe>s kleine, zickige, störrische Mistviecher sind, an die man nur ganz schwer ran kommt. Mehr muss man da gar nicht wissen.

Was die Vorschau zickig macht

Nun ist es so: Es gibt ein eigenes Smarty-Template für die Vorschau im Backend, über die sich beeinflussen lässt, was in diesem <iframe>, in dem die Backend-Vorschau eines Artikels erzeugt wird, dargestellt wird. Im Prinzip baut man damit die index.tpl (Serendipitys „Rahmen-Template“) nach, muss aber ein paar Ergänzungen vornehmen. So ziemlich das Wichtigste und gleichzeitig „historisch“ Problematischste dabei: Dem <iframe> muss die Höhe der Vorschau als Inline-Style per Javascript zugewiesen werden. Man muss quasi die Höhe eines Dokumentes ermitteln, um sie einem Container eine Ebene höher im DOM zuzuweisen, damit die Vorschau korrekt angezeigt wird. Klingt kompliziert, liegt aber nur daran, dass es blöd zu erklären ist.

Früher™ haben wir das so gelöst, dass in der preview_iframe.tpl (der Template-Datei für den Inhalt der Vorschau) im ein möglichst weit außen liegendes Element im Layout (ein äußerer Container) eine ID haben musste. Dann hat man per Javascript die Höhe dieses Containers ermittelt, den margin nach oben und unten dazu gerechnet und angenommen, dass das eine ausreichende Schätzung der Höhe der Vorschau sei. Was es nicht unbedingt war, weil sich natürlich das (Frontend-)Layout eines Themes nicht wirklich darum schert, dass es gut in eine Backend-Vorschau passt. Also musste man z.T. dem Container und/oder anderen Elementen Inline-Styles zuweisen, um Dinge wie border oder padding zu überschreiben, damit die Höhe richtig berechnet wurde.

Alles kann ein Container sein

Als ich neulich an einem neuen Serendipity-Theme (basierend auf Skeleton) bastelte und mich einmal mehr mit dieser #&!?$ Backend-Vorschau herumschlug, dachte ich so: „Wie schön es wäre, wenn wir ein Container-Element im Layout hätten, das immer vorhanden ist, immer eindeutig erfassbar ist und dessen Höhe selten bis nie durch Dinge wie (vertikales) padding oder border verzerrt wird“. Und dann fiel mir auf: So ein Element gibt es – <html>.

Es ist tatsächlich so simpel – man braucht keine zusätzlichen Elemente, keine Inline-Styles und selbst das Javascript zur Bestimmung der Höhe vereinfacht sich:

parent.document.getElementById('serendipity_iframe').style.height = document.querySelector('html').offsetHeight + 'px';
parent.document.getElementById('serendipity_iframe').scrolling    = 'no';
parent.document.getElementById('serendipity_iframe').style.border = 0;

Die letzten beiden Zeilen haben mit der Höhe der Vorschau eigentlich nichts zu tun, sie sorgen dafür, dass der <iframe> für die Vorschau weder einen Scrollbalken noch einen Rahmen hat. Könnte man – denke ich – in den meisten Fällen auch weglassen.

Man vergisst gerne, dass auch <html> oder <body> HTML-Elemente und Teil des DOM sind, womit man sie durchaus auch als Container benutzen kann. Dieser „Erkenntnis“ ist nicht mal neu, das ist nicht, was Browser erst seit ein paar Monaten „können“ oder so, Kroc Cramen hat das schon 2010 beschrieben. Allerdings gibt es zwischen <html> und <body> durchaus Unterschiede.