WordPress unterscheidet klassische Themes und Block Themes an genau einer Stelle: WP_Theme::is_block_theme() prüft, ob templates/index.html existiert (ersatzweise der alte Pfad block-templates/index.html). Mehr steckt nicht hinter der Weiche. Eine einzige Datei entscheidet, welche Admin-Bildschirme erscheinen, welche Theme-Supports automatisch gesetzt werden und ob der Site-Editor komplette Templates anfasst.
Mit WordPress 5.9 (Januar 2022) kamen Block Themes und der Site-Editor in den Core, damals unter dem Label Full Site Editing. Stand heute ist 7.1.1 die stabile Version, das mitgelieferte Standard-Theme ist laut WP_DEFAULT_THEME weiterhin Twenty Twenty-Five, und die Entscheidung zwischen beiden Architekturen ist deutlich weniger dramatisch geworden, als sie 2022 klang. Zwei der drei Argumente, die damals für Block Themes sprachen, gelten inzwischen auch für klassische Themes.
Dieser Text geht die Unterschiede durch, die in einem Projekt tatsächlich Arbeit verursachen: die Anatomie der Dateien, die Rolle von theme.json, der Verbleib von Menüs und Widgets, die Performance-Rechnung nach WordPress 6.9 und die Frage, wer die Seiten später zusammenstellt.
1. Anatomie: PHP vs. HTML
Klassisches Theme
Die Template-Hierarchie lädt PHP-Dateien: single.php, page.php, archive.php, dazu header.php und footer.php über get_header() und get_footer(). Jede Datei darf beliebiges PHP ausführen, Abfragen absetzen, eigene Klassen instanziieren. Das ist der Grund, warum Portale mit Fachlogik seit Jahren hier bleiben.
- Struktur:
index.php,header.php,page.php,sidebar.php,functions.php. - Vorteil: Kontrolle über jede Zeile Ausgabe, direkter Zugriff auf
WP_Query,get_template_part()und beliebige Drittbibliotheken. - Nachteil: Alles außerhalb des Inhaltsbereichs ist ohne Deployment nicht änderbar. Der Kopfbereich gehört der Agentur, nicht der Redaktion.
Block Theme
Das Minimum ist style.css plus templates/index.html. Die Templates sind HTML-Dateien mit Block-Kommentaren, die Teile liegen in parts/. Die Ordnernamen liefert get_block_theme_folders(): standardmäßig templates für wp_template und parts für wp_template_part. Fest verdrahtet sind sie nicht. Liegt im Stylesheet-Verzeichnis noch block-templates oder block-template-parts, schaltet WP_Theme::get_block_template_folders() auf diese alten Namen um (src/wp-includes/class-wp-theme.php, Zeilen 1808 bis 1825).
- Struktur:
templates/index.html,templates/single.html,parts/header.html,theme.json. - Vorteil: Die Redaktion bearbeitet Kopf, Fuß und Archivlayouts selbst, ohne Ticket.
- Nachteil: Die Template-Datei kennt kein PHP, und die Redaktion kann Layouts auch kaputt machen.
Der Satz “kein PHP” stimmt so nicht
functions.php wird in Block Themes genauso geladen wie vorher. Hooks, eigene Post-Typen, REST-Felder, alles unverändert. Was verschwindet, ist PHP in der Template-Datei. Für dynamische Werte im Markup gibt es drei dokumentierte Wege:
- Block Bindings, seit WordPress 6.5. Ein Attribut wird nicht mehr im Beitrag gespeichert, sondern zur Renderzeit von einem PHP-Callback geliefert, registriert über
register_block_bindings_source()mitget_value_callbackunduses_context. Welche Blöcke und Attribute das unterstützen, steht nicht in einer Doku, sondern inget_block_bindings_supported_attributes():core/paragraphundcore/headingjeweilscontent,core/imagemitid,url,title,altundcaption,core/buttonmiturl,text,linkTargetundrel, dazucore/post-date,core/navigation-linkundcore/navigation-submenu.core/list-itemist in WordPress 7.1 dazugekommen. Erweitern lässt sich die Liste über den Filterblock_bindings_supported_attributes. - Eigene Blöcke mit
render_callback, registriert ausblock.json. Das ist der Ort für alles, was validierte Attribute braucht, also etwa eine Standortliste mit Öffnungszeiten aus einem eigenen Post-Typ. core/pattern, ein serverseitig gerenderter Block. Steht<!-- wp:pattern {"slug":"theme/kontaktzeile"} /-->in einer Template-Datei, wird das Muster bei jedem Aufruf aus der Registry geholt. Ändert sich die PHP-Datei des Musters, ändert sich die Ausgabe. Beim Einfügen in einen Beitrag wird dasselbe Muster dagegen einmalig ausgeklappt und ist danach eine Kopie.
Wer in einem Block Theme die Fachlogik vermisst, sucht sie meistens an der falschen Stelle. Sie gehört in einen Block oder eine Binding-Quelle, nicht in die Vorlage.
2. Das Herz des Themes: functions.php vs. theme.json
In klassischen Themes war functions.php der Sammelplatz: Menüpositionen, Sidebars, Bildgrößen, Enqueues, Farbpaletten für den Editor. In Block Themes wandert die Konfiguration nach theme.json, und zwar in Schemaversion 3. Im Core steht das als Konstante: WP_Theme_JSON::LATEST_SCHEMA = 3. Eine Version 4 existiert nicht, auch wenn Blogbeiträge aus dem letzten Jahr etwas anderes behaupten.
Die Datei trennt zwei Dinge, die gern vermischt werden. settings legt fest, was der Editor überhaupt anbieten darf. styles legt fest, wie es aussieht, solange niemand etwas überschreibt. Jeder Palettenwert wird zu einer CSS-Variablen nach dem Muster --wp--preset--color--{slug} plus einer Utility-Klasse .has-{slug}-color, Schriftgrößen und Abstände analog.
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {
"color": {
"custom": false,
"defaultPalette": false,
"palette": [
{ "slug": "basis", "name": "Basis", "color": "#ffffff" },
{ "slug": "kontrast", "name": "Kontrast", "color": "#141414" }
]
},
"typography": { "customFontSize": false }
}
}Die Datenbank schlägt Ihre Datei
Das ist der Fehler, der in Projekten die meiste Zeit kostet. WP_Theme_JSON::VALID_ORIGINS ist default, blocks, theme, custom, in dieser Reihenfolge. custom sind die Werte aus dem Site-Editor, gespeichert als Beitrag vom Typ wp_global_styles. Wer einmal im Editor auf Speichern geklickt hat, sieht Änderungen an theme.json für die betroffenen Werte nicht mehr. Dasselbe gilt für Templates: get_block_templates() fragt zuerst die Beiträge ab und kommentiert das im Quelltext selbst mit “If the query has found some user templates, those have priority over the theme-provided ones”. Eine geänderte single.html im Deployment erreicht eine im Editor angefasste Vorlage nicht.
Die Konsequenz für den Betrieb: entweder die Redaktion fasst Templates an und das Repository ist nicht mehr die Wahrheit, oder Sie sperren die Bearbeitung für alle außer einer Rolle. Beides ist vertretbar, die stillschweigende Mischung nicht. Der Export im Site-Editor legt templates/ und parts/ als ZIP ab, das ist der offizielle Rückweg in Git.
Klassische Themes dürfen theme.json auch
Das wird regelmäßig übersehen. Ein klassisches Theme mit theme.json bekommt dieselben Presets, dieselben CSS-Variablen und seit Neuerem auch einen Eintrag im Menü: wp-admin/menu.php setzt den Design-Bildschirm, wenn current_theme_supports( 'editor-styles' ) oder wp_theme_has_theme_json() zutrifft, andernfalls nur den Muster-Bildschirm. Ein bestehendes Theme kann also die Token-Verwaltung übernehmen, ohne dass eine einzige PHP-Vorlage verschwindet. Wie so ein Token-Vertrag aussieht, steht ausführlich im Beitrag zu skalierbaren Design-Systemen mit Gutenberg.
Was in functions.php bleibt: Enqueues für eigene Skripte, Post-Typen, Hooks, Block-Registrierungen, Bildgrößen, Bindings-Quellen. theme.json ersetzt die Konfiguration des Aussehens, nicht die Programmierung.
3. Was ist mit Widgets und Menüs?
Die verbreitete Erklärung lautet, Block Themes hätten keine Menüs und keine Widgets. Der Core sagt etwas Genaueres, und der Unterschied ist praktisch relevant.
Menüs. In wp-admin/menu.php hängt der Eintrag an einer Bedingung: current_theme_supports( 'menus' ) || current_theme_supports( 'widgets' ). Block Themes setzen diese Supports nicht automatisch, deshalb ist der Bildschirm weg. Ein add_theme_support( 'menus' ) im Block Theme holt ihn zurück, samt wp_nav_menu() in einem eigenen Block. Für Redaktionen, die seit Jahren mit dem Menü-Bildschirm arbeiten, ist das ein legitimer Zwischenschritt.
Widgets. wp_widgets_add_menu() prüft current_theme_supports( 'widgets' ), und dieser Support wird durch register_sidebar() gesetzt. Ein Block Theme, das eine Sidebar registriert, bekommt den Widgets-Bildschirm also wieder, im Menü hinten angehängt statt an Position 8. Die alten Widget-Daten gehen beim Wechsel ohnehin nicht verloren: switch_theme() schreibt die registrierten Sidebars in den Theme-Mod wp_classic_sidebars, und _wp_block_theme_register_classic_sidebars() meldet sie beim Block Theme wieder an. Der Weg von Widgets zu Blöcken ist im Beitrag von Classic Widgets zu Blöcken beschrieben.
Der Customizer verschwindet ebenfalls nicht per Dekret. Er wird nur ausgeblendet, wenn ein Block Theme aktiv ist und kein Plugin etwas an customize_register hängt. Sobald ein Plugin dort eine Einstellung registriert, ist der Menüpunkt wieder da. Zusätzlich verschiebt _add_themes_utility_last() den Theme-Datei-Editor bei Block Themes von Design nach Werkzeuge, was beim ersten Mal reliabel für Verwirrung sorgt.
Navigation als Datenbankobjekt. Der Navigations-Block speichert Menüs nicht im Theme, sondern als Beiträge vom Typ wp_navigation mit show_in_menu => false. Damit gilt für Menüs dasselbe wie für synchronisierte Muster und globale Styles: sie liegen in der Datenbank, nicht im Repository. Staging und Produktion haben jeweils eigene Objekte. Wer ohne Content-Sync deployt, baut die Navigation zweimal.
| Objekt | Post-Typ | Wo es lebt | Kommt es mit dem Deployment mit |
|---|---|---|---|
| Template-Datei | keiner | templates/*.html, in Git | ja, solange niemand es im Editor gespeichert hat |
| Bearbeitetes Template | wp_template | Datenbank | nein |
| Bearbeiteter Template-Part | wp_template_part | Datenbank | nein |
| Globale Styles | wp_global_styles | Datenbank | nein |
| Navigationsmenü | wp_navigation | Datenbank | nein |
Muster aus /patterns | keiner | Theme-Ordner, in Git | ja |
4. Performance
Hier stand jahrelang das stärkste Argument für Block Themes, und genau dieses Argument ist seit WordPress 6.9 weitgehend erledigt.
Was früher galt. _add_default_theme_supports() setzt für Block Themes automatisch should_load_separate_core_block_assets und should_load_block_assets_on_demand auf true. Klassische Themes bekamen stattdessen standardmäßig die gebündelte wp-block-library-Datei, rund 120 Kilobyte, auf jeder Seite. Ein Opt-in existierte, add_filter( 'should_load_separate_core_block_assets', '__return_true' );, aber die getrennten Blockstyles wurden dann im Fußbereich geladen, mit ungestyltem Zwischenbild als Folge.
Was seit 6.9 gilt. wp_load_classic_theme_block_styles_on_demand() setzt dieselben beiden Filter für klassische Themes, sofern es sich nicht um ein Block Theme handelt und die Seite nicht aus dem Template-Enhancement-Output-Buffer ausgestiegen ist. Der Buffer, ebenfalls neu in 6.9, sammelt spät ausgegebene Styles ein und hebt sie in den Kopfbereich, damit kein ungestyltes Zwischenbild entsteht. Der Frontend-Performance-Field-Guide zu 6.9 nennt dafür im Durchschnitt 45 Prozent weniger CSS auf der Beispielseite über die mitgelieferten Themes hinweg und 26 Prozent auf Seiten mit mehr Blöcken.
Der Preis steht im selben Dokument. Ein Output-Buffer verhindert Streaming. Für klassische Themes auf der Beispielseite misst das Core-Team eine TTFB von plus 1,95 Millisekunden, also plus 7,1 Prozent, und formuliert den Effekt ausdrücklich: die Gesamtantwortzeit bleibt ungefähr gleich, die Zeit bis zum ersten Byte steigt. Für ein Projekt mit langsamer Fachlogik vor der Ausgabe ist das eine Abwägung, kein Geschenk. Abschalten lässt es sich über den Filter wp_should_output_buffer_template_for_enhancement oder durch Zurücksetzen der beiden Style-Filter, beide sind mit Priorität 0 registriert, damit ein Theme sie schlagen kann.
Ebenfalls in 6.9: das Limit für eingebettete Styles steigt von 20 auf 40 Kilobyte. Die zugrunde liegende Messung zeigt bei Erstbesuchen ein um 205,8 Millisekunden kürzeres LCP-minus-TTFB, minus 31,39 Prozent, bei wiederholten Besuchen ein um 30,3 Millisekunden längeres, plus 21,44 Prozent. Für Seiten mit hohem Anteil an Erstbesuchern ist das ein guter Tausch, für ein Intranet der schlechtere.
Zur Lighthouse-Zahl. Ein Theme liefert keinen Lighthouse-Score, eine Seite liefert ihn. Die mitgelieferten Block Themes sind leicht, ihre minifizierten Stylesheets liegen nach 6.9 bei wenigen Kilobyte, für Twenty Twenty-Five bei rund 600 Byte. Auf einer echten deutschen Firmenseite entscheiden darüber trotzdem andere Dinge: das Consent-Banner, das vor allem anderen lädt, eingebettete Karten und Formulardienste, Schriftdateien und unoptimierte Bilder aus der Mediathek. Wer Zahlen will, misst die eigene Seite. Der Weg dahin steht im Leitfaden zu Core Web Vitals 2026.
5. Strategie für 2026: Was wählen?
Die Technik gibt die Antwort nicht her, die Zuständigkeit schon. Die eine Frage, die Sie vor dem Kickoff klären sollten: wer ändert in achtzehn Monaten den Kopfbereich, und was passiert, wenn diese Person ihn zerlegt.
Klassisches Theme, wenn:
- viel Fachlogik vor der Ausgabe liegt, etwa Preisberechnung, ERP-Abfragen, Mandantenlogik,
- ein Page Builder im Einsatz ist und bleibt, siehe den Vergleich Gutenberg gegen Elementor und Divi,
- die Redaktion bewusst nur Inhalte pflegen soll und das Layout verbindlich bleibt,
- ein bestehendes Theme funktioniert und niemand ein neues Budget dafür hat. Presets nachrüsten geht auch so.
Block Theme, wenn:
- Marketing eigene Landingpages aus Mustern bauen soll,
- Kopf, Fuß und Archivseiten ohne Deployment änderbar sein müssen,
- das Projekt neu startet und keine Altlasten in der Vorlagenschicht hat.
Hybrid, für fast alle Bestandsprojekte. Ein klassisches Theme darf theme.json mitbringen, add_theme_support( 'block-template-parts' ) setzen (seit WordPress 6.1) und damit Kopf und Fuß im Site-Editor bearbeitbar machen, während der Rest der Template-Hierarchie in PHP bleibt. Das ist der einzige Migrationspfad, der sich in Etappen bezahlt macht: erst Tokens nach theme.json, dann wiederkehrende Layouts nach /patterns, dann Kopf und Fuß als Block-Template-Parts, und erst wenn das trägt, templates/index.html anlegen und damit die Weiche umlegen.
Zwei Punkte, die im deutschsprachigen Markt zusätzlich zählen
Barrierefreiheit. Das Barrierefreiheitsstärkungsgesetz gilt seit dem 28. Juni 2025 und verweist auf die EN 301 549, die ihrerseits auf WCAG 2.1 Stufe AA zeigt. Kleinstunternehmen im Dienstleistungsbereich sind ausgenommen, Webshops und Buchungsstrecken in aller Regel nicht. Ein Block Theme legt die Überschriftenebenen, Kontraste und Linktexte in die Hände der Redaktion. Das ist kein Argument dagegen, aber ein Argument für gesperrte Paletten in theme.json (color.custom: false), für templateLock auf den Seitentypen, die auf Kurs bleiben müssen, und für eine Abnahme mit einem Redakteurskonto statt mit einem Administratorkonto.
Schriften und Datenschutz. Die klassische Gewohnheit, Google Fonts in functions.php per wp_enqueue_style() von fonts.googleapis.com zu laden, ist seit dem Urteil des Landgerichts München I vom 20. Januar 2022 (Az. 3 O 17493/20) ein absehbares Abmahnrisiko. Die Font Library aus WordPress 6.5 lädt Schriftdateien in wp-content/uploads/fonts (siehe _wp_filter_font_directory()) und bindet sie von dort ein. Das funktioniert unabhängig vom Theme-Typ, wird aber im Block-Workflow zuerst angeboten, während in klassischen Themes der alte Enqueue oft unbemerkt stehen bleibt.
Zusammenfassung
Die Wahl ist 2026 kleiner geworden. Das Performance-Argument ist seit 6.9 weitgehend ausgeglichen, theme.json steht beiden Architekturen offen, Menüs und Widgets hängen an Theme-Supports statt am Theme-Typ. Was bleibt, ist die Frage nach der Zuständigkeit für die Vorlagen und die betriebliche Folge daraus: sobald der Site-Editor genutzt wird, liegen Templates, Styles und Navigation in der Datenbank, und Ihr Deployment erreicht sie nicht mehr.
Wenn Sie theme.json, Muster und die Sperren im Site-Editor nicht selbst aufsetzen wollen, übernimmt das unsere WordPress-Entwicklung für Block-Themes. Wir setzen den Token-Vertrag auf und klären vorab, welche Objekte in Git liegen und welche in der Datenbank.





