Mit einem Monat Verspätung am 25. Januar 2022 erschienen, war WordPress 5.9 die erste Ausgabe der populären Blog-Software mit aktiviertem Full Site Editing (FSE). Will sagen: Der 2018 erstmals ausgelieferte Block-Editor Gutenberg kümmert sich nicht mehr nur um den Inhalt von Posts oder Pages, sondern um die gesamte Seite, vom Header bis zum Footer. Alles ist gebaut aus Blöcken – auch das Menü und der berühmt-berüchtigte Loop sind nun Blöcke.
Für alle, die ein eigenes Theme entwickeln wollen, heißt das: Templates und Template Parts werden nicht mehr in PHP-Dateien mit einem schwer leserlichen Mix aus PHP und HTML notiert, sondern … in HTML-Dateien mit einem schwer leserlichen Mix aus HTML und mit Json-Objekten gefüllten HTML-Kommentaren. Nun ja. Aber schauen wir uns das Ganze mal in der Praxis an. Was ändert sich bei der Theme-Entwicklung?
Mit Twenty Twenty-Two liefert WordPress 5.9 erstmals ein echtes Block Theme aus, zudem findet sich im Github-Repository von WordPress ein Empty Theme, das ich mir als – allerdings sehr rudimentären – Startpunkt für eigene Block Themes per git clone
ebenfalls installiert habe. Neuerdings kann man sich auch von Carolina Nymarks Block Theme Generator ein Theme erzeugen lassen und dabei aus drei Funktionsumfängen wählen. Im offiziellen Theme-Verzeichnis auf WordPress.org nimmt die Zahl der mit „full-site-editing“ getaggten Einträge ebenfalls zu.
Dass diese Block Themes anders sind, signalisiert schon die veränderte Ordnerstruktur: Neu sind die Unterverzeichnisse templates
und parts
, in denen die HTML-Dateien für Templates und Template-Teile erwartet werden. Seit WordPress 6.0 darf es zusätzlich ein Verzeichnis patterns
für Block Patterns, also vordefinierte und -gestylte Block-Zusammenstellungen, geben.
Außerdem liegt im Wurzelverzeichnis die neue Über-Konfigurationsdatei theme.json
, jetzt in der stark erweiterten, aber immer noch nicht ganz kompletten Version 2; dazu in Kürze mehr in einem separaten Beitrag.
Was sich nicht geändert hat: Im Wurzelverzeichnis eines jeden Themes muss sich eine Datei style.css
finden, die mit einem Kommentarblock beginnt, der den Namen des Themes und weitere Pflichtangaben beinhaltet.
Schließlich wären da noch die letzten PHP-Dateien, die übrig geblieben sind: functions.php
und index.php
. Hier ist nun eine kleine Gedenkminute angebracht.
Auf die einstige Spaghetti-Code-Zentrale eines jeden WordPress-Themes, die functions.php
, sind Block Themes nämlich gar nicht mehr angewiesen. Und die index.php
, die einst das Standard-Template einer jeden WordPress-Website enthielt, ist nur noch eine Datei ohne Inhalt; PHP-Templates braucht man ja – siehe oben – nicht mehr. Paradoxerweise lassen sich Block Themes ohne index.php trotzdem nicht aktivieren. Wie das künftig gehandhabt werden soll, darüber wurde bei Veröffentlichung von WordPress 5.9 noch diskutiert. Seit WordPress 6.0 lassen sich Block Themes aber auch ohne index.php aktivieren – sofern die Datei templates/index.html enthalten ist.
Eine CSS-Datei ist (k)eine CSS-Datei
Noch ein Paradoxon: Block Themes machen aus der style.css
eine CSS-Datei ohne CSS, weil jeder Block sein eigenes Styling mitbringen darf und globale Stile sowie die Stile der Core-Blöcke in der theme.json
definiert werden.
Wenn nun Twenty Twenty-Two dennoch eine style.css
ausliefert, die tatsächlich CSS-Code nach dem Kommentarblock enthält, dann liegt das daran, dass in WordPress 5.9 noch ein paar Nickligkeiten ausgebessert werden müssen. Wer mehr wissen will, schaue sich den mit Links zu den betreffenden Bugs gut dokumentierten Quelltext an.
Bis auf Weiteres sei deshalb Block-Theme-Entwicklern empfohlen, diese Stile in eigenen Kreationen zu übernehmen und Updates der style.css
in Twenty Twenty-Two entsprechend nachzuvollziehen.
Was von der Spaghetti-Code-Zentrale functions.php übrig blieb
Solange die style.css
noch CSS beinhaltet, muss man sie wie gewohnt in der functions.php
als Stylesheet registrieren und sollte diese Stile auch im Editor verfügbar machen, damit im Backend möglichst alles so aussieht wie im Frontend:
function my_theme_assets() {
wp_enqueue_style( 'my-theme-style', get_template_directory_uri() . '/style.css', [], wp_get_theme()->get( 'Version' ) );
}
add_action( 'wp_enqueue_scripts', 'my_theme_assets' );
function my_theme_support() {
add_theme_support( 'wp-block-styles' );
add_editor_style( 'style.css' );
}
add_action( 'after_setup_theme', 'my_theme_support' );
Bei dieser Gelegenheit habe ich mit der Funktion add_theme_support() das Feature wp-block-styles
eingeschaltet. Es sorgt dafür, dass die bei WordPress immer mitgelieferten Core-Blöcke ein etwas feineres Styling erhalten. Beispiel: Ein Gruppen-Block mit Hintergrundfarbe bekommt nur mit Support für wp-block-styles
ein ordentliches padding um seinen Inhalt herum. Alle Block Styles werden übrigens inline im HTML-Head eingebunden.
Da es die neue Webfonts-API noch nicht wie ursprünglich geplant in WordPress 5.9 geschafft hat, müssen eigene Schriften zunächst noch händisch geladen werden. Auch dazu muss man über die functions.php
ein Stylesheet laden.
Weitere Dinge, die nach wie vor über die functions.php
registriert werden müssen:
- Eigene Block-Patterns: über den init-Hook mit register_block_pattern. Ebenso kann man die von WordPress mitgelieferten Core-Block-Patterns deaktivieren:
remove_theme_support( 'core-block-patterns' );
- Die Textdomain für mehrsprachige Themes: über den after-team-setup-Hook mit load_theme_textdomain.
Vom PHP-Template zum Block Template
Bislang haben Theme-Entwickler Templates für WordPress in PHP-Dateien im Wurzelverzeichnis eines Themes notiert. Dabei reichte im einfachsten Fall eine einzige Template-Datei aus: index.php. Seiten-Header und -Footer wurden in eigene PHP-Dateien ausgelagert und per get_header() bzw. get_footer() aufgerufen, während der Haupt-Inhalt der Seite, also der page oder post content, über den Loop aus der Datenbank gefischt und ausgegeben wurde.
Daran änderte sich auch bei Einführung des Gutenbergs-Editors erst einmal gar nichts – Templates sowie Header und Footer wurden weiterhin in PHP-Templates kodiert.
Erst das Full-Site-Editing macht aus der gesamten Seite Blöcke und damit auch Header und Footer zu Template-Teilen, die aus Blöcken bestehen. Die früher über get_sidebar()
geladenen Widget-Bereiche gibt es gar nicht mehr.
Schauen wir statt dessen besser auf fertigen Code. Im folgenden Beispiel habe ich ein Template index.html
(mit Loop) verfasst und zum Vergleich die Oldschool-Variante in PHP dazugestellt:
<!-- wp:template-part {"slug":"header","tagName":"header","className":"site-header"} /-->
<!-- wp:query {"tagName":"main","layout":{"inherit":true}} -->
<main class="wp-block-query"><!-- wp:post-template -->
<!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-excerpt {"moreText":"Mehr","showMoreOnNewLine":false} /-->
<!-- /wp:post-template --></main>
<!-- /wp:query -->
<!-- wp:template-part {"slug":"footer","tagName":"footer","className":"site-footer"} /-->
<?php get_header() ?>
<main id="site-content" role="main">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<article <?php post_class(); ?> id="post-<?php the_ID(); ?>">
the_title( '<h1 class="entry-title">', '</h1>' );
the_content( 'Mehr' );
</article>
<?php endwhile; endif; ?>
<?php get_footer() ?>
Wer sich schon einmal ein WordPress-Template in PHP angeschaut hat, der sollte sich auch auf die Block-Variante einen Reim machen. Ich verzichte deshalb darauf, diesen Code Zeile für Zeile zu kommentieren und alle für das Full Site Editing relevanten neuen Blöcke einzeln aufzuführen; statt dessen sei auf die Fleißarbeit von Carolina Nymark sowie auf die offizielle Core-Blocks-Referenz verwiesen. Letztere listet die verfügbaren Attribute unterstützten Features für jeden Block und eignet sich deshalb als Cheatsheet für das eigenhändige Coden von Templates.
Neue Post Types
Hinter den Kulissen haben die WordPress-Entwickler für Templates, Template-Teile und für den Navigations-Block neue Post Types kreiert. Sobald also eine Template- oder Template-Teil-Datei im Site-Editor angepasst wird, werden die Daten in der Tabelle wp-posts gespeichert. Im Site-Editor werden solche geänderten Templates dann mit einem blauen Punkt gekennzeichnet.
Für den Navigations-Block bedeutet dies: Die einzelnen Menüs werden zentral gespeichert und können von jedem installierten Theme aus eingebunden werden. Aber natürlich kann jedes Theme die Navigation unterschiedlich stylen. Daten und Präsentation werden also sauber getrennt. Auch wenn es die alte Menüverwaltung im Customizer nicht mehr gibt, lassen sich bereits konfigurierte „klassische“ Menüs ebenfalls über den Navigations-Block einbinden; sie werden konvertiert und diese Umwandlung lässt sich danach nicht mehr rückgängig machen, außer per Backup.
Was wird aus dem Customizer?
A propos Customizer: Diesen gibt es in Block Themes nicht mehr (auch wenn es auf der Theme-Seite immer noch einen missverständlich benannten Button „Customize“ gibt, der zum Site Editor führt). Wirklich weg ist der Customizer abert nicht. Er erscheint wieder, wenn ein klassisches Theme aktiviert wird oder ein Plugin es erfordert.
An sich ist es nicht schade um den Customizer, weil sein Funktionsumfang ohnehin stark vom jeweiligen Theme anhängig war – während der Site Editor, der ihn ersetzt, als Bestandteil des Cores immer alle möglichen Features mitbringt. Allerdings ist die Vorschau eines anderen Themes als des gerade aktivierten mit dem Site Editor nicht möglich. Im Customizer ging das.
Fehleranfällige HTML-Kommentar-Notation in Templates
Autoren von Block Themes müssen die Konfiguration ihrer Blöcke in HTML-Kommentaren notieren. Da gibt es, ähnlich wie bei echten HTML-Elementen, zwei Typen:
- Solche, die sich selbst schließen:
<!-- wp:block_name {"schlüssel":"wert", ...} /-->
- Solche mit einem öffnenden und einem schließenden Tag, die weitere Inhalte enthalten:
<!-- wp:block_name {"schlüssel":"wert", ...} /-->
[...]
<!-- /wp:block_name -->
Vor allem letztere sorgen für Unübersichtlichkeit, weil der öffnende HTML-Tag, den sie erzeugen, zusätzlich hinter dem HTML-Kommentar mit dem öffnenden Block-Tag notiert werden muss – und der schließende HTML-Tag zusätzlich vor dem HTML-Kommentar mit dem schließenden Block-Tag. Das ist doppelt-gemoppelt. Man schaue sich als Beispiel den wp:query
-Tag ben im Beispiel-Code für den Loop an.
Solche Redundanz provoziert auch Fehler: Wenn nämlich die im HTML-Kommentar konfigurierten Json-Parameter und der HTML-Code voneinander abweichen, dann ist der Block kaputt und es wird einem im Editor die in dieser Situation völlig nutzlose Block-Wiederherstellung angeboten.
Anstatt also diesen HTML-Code mit seinen in Kommentaren verpackten JSON-Objekten in einen Texteditor zu tippen, klickt man Templates und Template-Teile besser visuell zusammen. Das gelingt im Site Editor, der bei WordPress 5.9 erstmals serienmäßig – allerdings noch mit dem Zusatz „beta“ – an Bord ist. Man erreicht ihn über den Menüpunkt „Design“.
Und so sieht mein oben dargestellter Template-Code einer index.html
mit etwas Styling, auf das ich im Beitrag über die theme.json
eingehen werde, im Site-Editor aus:
Templates in der Template-Hierarchie erstellen
Von Haus aus kennt WordPress eine Reihe von Templates mit reservierten Namen – neben Index sind das Home, Singular, Page, Archive, Search und 404, und die Template-Hierarchie ist dafür zuständig zu entscheiden, in welchem Template die aufgerufene Seite dargestellt wird. Das war schon immer so – nur dass die Template-Dateien eben nicht mehr mit .php
-, sondern mit .html
-Namenserweiterung abgespeichert werden.
Alle Templates eines Themes werden im Site Editor unter den Menüpunkt „Templates“ gemanagt:
Über den „Hinzufügen“-Button lässt sich ein neues Template erstellen – allerdings in WordPress 5.9 nur eines der oben genannten Standard-Templates. Templates mit zusammengesetztem Namen wie Category-{Slug}, die ebenfalls Teil der Template-Hierarchie sind, lassen sich über den Site Editor erst seit WordPress 6.0 erstellen.
Als Workaround für 5.9 legt man – ähnlich wie bei dem gleich noch beschriebenen Custom Templates – einfach eine (zur Not auch leere) Datei in den Ordner templates
und gibt ihr einen Namen nach dem Muster category-{slug}.html
. Danach ist dieses Template im Site Editor verfügbar.
Dass der Site Editor noch längst nicht fertig ist, zeigt auch der Umstand, dass man nach dem „Hinzufügen“ bei Null anfängt, also mit einem leeren Template. Besser ist es deshalb, als Ausgangspunkt ein existierendes Template zu recyceln, um davon das neue abzuleiten.
Beispiel: Wir haben bereits ein Page-Template und wollen auf dieser Basis ein Home-Template für eine spezielle Startseite erstellen. Das geht (noch) nicht direkt im Site Editor, aber über einen Umweg auf Dateiebene: Zuerst legt man eine neue Template-Datei home.html
im Ordner templates
an; dann kopiert man den Inhalt des Page-Templates und fügt ihn in die leere home.html
ein. Danach erscheint Home als neuer Eintrag im Site Editor und kann weiter angepasst werden.
Custom Templates einrichten
Unter dem Schlüssel customTemplates
lassen sich in der theme.json
aber auch Templates außerhalb der Hierarchie registrieren, die dann ebenfalls im Site Editor bearbeitet werden können.
Angenommen, wie benötigen ein spezielles Template für eine Seite, auf der Team-Mitglieder vorgestellt werden. Da WordPress dieses Template nicht kennt, muss man – neben dem Namen und einem Titel, der im Site Editor angezeigt wird – zusätzlich den oder die Post Types definieren, für die dieses „Team“-Template zuständig sein soll:
"customTemplates": [
{
"name": "team",
"title": "Team Page",
"postTypes": [
"page"
]
}
]
Trotz Registrierung in der theme.json
tauchte dieses Custom Template bei mir aber erst im Site Editor auf, nachdem ich zusätzlich eine Datei mit dem Namen team.html
im Ordner templates
angelegt hatte.
Wie kann ich nun mein „Team“-Template einer Seite zuordnen? Indem ich die gewünschte Seite anlege oder bearbeite, unter Einstellungen den Reiter „Seite“ anklicke und dort anstelle des laut Template-Hierarchie voreingestellten „Standard-Templates“ meine neue „Team Page“ auswähle. Nach demselben Muster lassen sich natürlich auch Beiträgen andere Templates zuordnen.
Header, Footer und andere Template-Teile erstellen
Auch für Template-Teile gibt es im Site Editor einen eigenen Menüpunkt:
Der Aufbau gleicht jenem des „Templates“-Screens.
Ähnlich wie Custom Templates sollten Template Parts in der theme.json
registriert werden. Dafür existiert der Schlüssel templateParts
. Neben dem Namen und dem Titel muss man angegeben, in welchen Bereich des Templates die Teile gehören. Möglich sind header
, footer
und uncategorized
. Unterlässt man die Registrierung in der theme.json
, wird der Template-Teil trotzdem im Site Editor angezeigt, aber eben uncategorized
(als Bereich wird in der deutschen Übersetzung „Allgemein“ angezeigt).
Hier der relevante Code für die theme.json
:
"templateParts": [
{
"name": "header",
"title": "Centered Header",
"area": "header"
},
{
"name": "footer",
"title": "Footer",
"area": "footer"
}
]
Das mit WordPress 6.1 erschienene Theme Twenty Twenty-three zum Beispiel liefert vier Template Parts mit: einen Header (Kategorie: Header), einen Footer (Kategorie: Footer) sowie Teile für Beitrags-Meta und Kommentare (Kategorie: Allgemein).
Templates und Template-Teile exportieren
Zum Schluss exportiert man das Blockhaus in einem Rutsch über das Drei-Punkte-Menü im Site-Editor und erhält damit ein Archiv edit-site-export.zip, das alle erstellten Templates und Template-Teile in den korrekten Verzeichnissen enthält, so dass man sie direkt im Wurzelverzeichnis des eigenen Themes entpacken kann.
Möchte man nur das gerade angezeigte Template – oder ein Stück davon – exportieren, so öffnet man die Listenansicht, klickt auf das Elternelement der zu kopierenden Blöcke (der gewünschte Teil sollte nun im visuellen Editor markiert sein) und dann mit der rechten Maustaste auf kopieren. Damit landet der betreffende Code in der Zwischenablage und kann in eine Template-Datei eingefügt werden.
… und PHP-Templates sind doch noch nicht tot
Auch wenn Templates nun als HTML-Dateien erzeugt werden, so ist es dennoch möglich, in einem Block Theme ein PHP-Template unterzubringen. Warum sollte das gewünscht sein? Nun, solange der Site-Editor noch nicht ausentwickelt ist, lassen sich mit gutem, alten PHP-Code Lücken stopfen. Um zum Beispiel einen Custom Post Type für Touren mit Custom Fields auszugeben, habe ich ein Template single-tour.php
im Wurzelverzeichnis abgelegt. WordPress sucht zuerst nach einem HTML-Template im templates-Ordner, danach nach einem PHP-Template im Wurzelverzeichnis.
Ein Beispiel für ein PHP-Template, das wiederum Blöcke verwendet, findet sich hier. Dieses Vorgehensweise funktioniert aber wegen eines Fehlers noch nicht 100-prozentig: WordPress liefert die Inline-Stile im HTML-Head nicht aus. Ein Workaroud findet sich in dem zugehörigen Bug-Report.
Fazit
Der Site-Editor ändert die Theme-Entwicklung in WordPress grundlegend. Auch wenn alte, mit PHP entwickelte Themes weiterhin funktionieren, so gehört die Zukunft eindeutig dem Full-Site-Editing. Leider offenbart Gutenberg im Detail immer noch viele Lücken (keine Pseudo-Klassen, keine absolute oder fixed Positionierung, etc.), die Theme-und Block-Entwickler mit eigenem CSS stopfen müssen.
Um Block-Templates zu erstellen, braucht man streng genommen gar kein Programmierer mehr zu sein, weil die WordPress-Entwickler die Logik hinter einer Block-API wegabstrahiert haben. Der berühmt-berüchtigte Loop präsentiert sich Theme-Entwicklern nur noch als Block, der visuell im Site Editor konfiguriert oder im Text-Editor als HTML-Kommentar-Code beschrieben wird. Mit WP_Query und WP_Post braucht sich niemand mehr herumzuschlagen, und das ist – denkt man an den früheren Code-Alptraum mit globalen Objektinstanzen – auch gut so. Jedenfalls kommt es Designern, die keine Programmierer sind, entgegen. Mit Json sollte man allerdings nicht fremdeln.
Die „Verlierer“ dieser Entwicklung, wenn man das so sagen will, sind die PHP-Entwickler. Hatte Gutenberg mit seinen Blöcken schon die Kehrtwende vom Server-seitigen PHP zum JavaScript-Frontend-Framework React vollzogen, so sind nun auch die Zeiten der PHP-Templates passé. Zur Ehrenrettung von PHP sei gesagt, dass der WordPress-Core weiterhin in dieser Skriptsprache entwickelt wird.
Verlierer sind sicher auch Elementor, Divi Builder, Brizzy und Co. Warum sollte man noch Geld für einen kommerziellen Page Builder ausgeben und sich in Abhängigkeit von einem separaten Hersteller begeben, wenn Gutenberg als offizieller WordPress-Editor dabei ist, die Lücke zu schließen?
So weit sind wir aber nicht. Block Themes sind immer noch ein Work in Progress, das merkt man an fehlenden Funktionen und an vielen einzelnen Ungereimtheiten beim Bedienen des Editors. Leider hält die offizielle Dokumentation nicht sehr gut Schritt mit der Weiter-Entwicklung, so dass man oft besser damit wegkommt, den Code existierender Block Themes zu studieren.
Literaturhinweise
Full Site Editing: Creating WordPress block themes
Danke für diesen guten und kritischen Artikel mit viel Insights!
Ich habe bisher immer in PHP entwickelt und konnte mich nie mit Javascript und React anfreunden. Doch mittlerweile habe ich gemerkt das sich hier ganz neue Möglichkeiten auftun und arbeite mich gerade in die Materie ein. Danke für deine überaus ausführlichen Beitrag dazu. Ich hoffe da kommt noch mehr!?