Zum Inhalt springen
Themes

WordPress theme.json verstehen: settings, styles und die Kaskade

Warum settings und styles in theme.json völlig verschiedene Aufgaben haben – und wie Sie Änderungen am Block-Theme reparieren, die sichtbar nichts bewirken.

Veröffentlicht

theme.json ist eine einzelne Konfigurationsdatei im Wurzelverzeichnis eines Block-Themes, die zwei voneinander getrennte Aufgaben erfüllt: settings entscheidet, was der Block-Editor den Benutzern anbietet, und styles entscheidet, wie die Website standardmäßig aussieht. WordPress parst die Datei, führt sie mit den eigenen Standardwerten und allem im Site-Editor Gespeicherten zusammen und gibt das Ergebnis auf jeder Seite als CSS-Custom-Properties plus Inline-Stylesheet aus.

Genau die Verwechslung dieser beiden Aufgaben ist der Grund, warum die meisten Änderungen an theme.json scheinbar wirkungslos bleiben. Eine unter settings deklarierte Farbe wird nirgendwo angewendet. Sie erzeugt lediglich eine Variable und ein Farbfeld in der Editor-Seitenleiste.

Die Schlüssel der obersten Ebene

Eine minimale Datei sieht so aus:

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {},
  "styles": {},
  "templateParts": [],
  "customTemplates": []
}
SchlüsselAufgabe
$schemaNur Autovervollständigung und Validierung im Code-Editor. WordPress ignoriert den Schlüssel.
versionLegt fest, nach welchem Schema WordPress parst. Nicht Ihre Theme-Version.
settingsErzeugt CSS-Variablen und steuert, was der Editor anbietet.
stylesWeist die tatsächlichen Standard-Styles zu.
templatePartsDeklariert die Teile in parts/ und ihren jeweiligen Bereich.
customTemplatesRegistriert Seitentemplates aus templates/ für den Beitragseditor.

version sorgt regelmäßig für Verwirrung, weil der Schlüssel wie eine Theme-Versionsnummer aussieht. Ist er nicht. Er wählt einen Parsing-Modus aus, und ältere WordPress-Ausgaben überspringen Schlüssel eines Schemas, das sie nicht kennen, kommentarlos. Wenn Sie ältere Installationen unterstützen, wählen Sie die Version, die diese Installationen verstehen, statt darauf zu setzen, dass neuere Schlüssel elegant ausfallen. Version 3 ist zum Zeitpunkt dieses Textes aktuell; Version 2 ist weiterhin weit verbreitet und wird weiterhin geparst.

$schema verweist auf eine von WordPress gehostete Schema-URL. Ein Verweis auf trunk liefert Ihnen die neuesten Hinweise im Code-Editor; eine versionsspezifische URL ist die sichere Wahl, wenn Sie bewusst auf einem älteren Schema bleiben.

settings: was der Editor anbietet

Alles unter settings erzeugt eine CSS-Custom-Property und in den meisten Fällen zusätzlich ein Bedienelement im Editor. Gestaltet wird dadurch nichts.

{
  "settings": {
    "color": {
      "palette": [
        { "slug": "brand", "color": "#1f4ed8", "name": "Brand" },
        { "slug": "ink", "color": "#111827", "name": "Ink" }
      ],
      "custom": false
    },
    "typography": {
      "fontSizes": [
        { "slug": "small", "size": "0.875rem", "name": "Small" },
        { "slug": "large", "size": "1.5rem", "name": "Large" }
      ]
    },
    "layout": {
      "contentSize": "680px",
      "wideSize": "1200px"
    }
  }
}

Daraus entstehen Variablen, deren Namen sich aus Preset-Pfad und Slug zusammensetzen:

--wp--preset--color--brand
--wp--preset--color--ink
--wp--preset--font-size--small
--wp--preset--font-size--large

Zusätzlich entstehen Utility-Klassen wie .has-brand-color und .has-brand-background-color – über sie überträgt der Editor ein ausgewähltes Farbfeld auf einen Block.

Die Zeile "custom": false steht für die andere Hälfte von settings: Optionen abschalten. Setzen Sie sie, verschwindet der freie Farbwähler, und den Benutzern bleibt Ihre Palette und sonst nichts. Dasselbe Muster gilt durchgängig – settings.typography.customFontSize, settings.spacing.customSpacingSize, settings.border und so weiter. Nichts unter settings ist Dekoration; jeder Schlüssel fügt entweder eine Variable hinzu, fügt ein Bedienelement hinzu oder entfernt eines.

settings.custom ist ein freier Bereich für eigene Variablen:

{
  "settings": {
    "custom": {
      "lineHeight": { "body": 1.6 },
      "shadow": { "card": "0 1px 3px rgba(0,0,0,0.12)" }
    }
  }
}

Daraus werden --wp--custom--line-height--body und --wp--custom--shadow--card. Beachten Sie die Umwandlung: camelCase-Schlüssel werden in Kebab-Case zerlegt, und Verschachtelung wird mit doppelten Bindestrichen verbunden. Ein falsch geschriebener Variablenname ist ein häufiger Grund dafür, dass ein Wert stillschweigend auf den Fallback zurückfällt.

Sie können Einstellungen pro Block einschränken – so erlauben Sie den Farbwähler etwa für Buttons, aber nicht für Absätze:

{
  "settings": {
    "blocks": {
      "core/paragraph": {
        "color": { "custom": false, "customGradient": false }
      }
    }
  }
}

styles: was tatsächlich gerendert wird

In styles werden Werte zugewiesen. Der Aufbau spiegelt die Struktur des Editors: eine Wurzelebene, dann elements, dann blocks.

{
  "styles": {
    "color": {
      "background": "var(--wp--preset--color--base)",
      "text": "var(--wp--preset--color--ink)"
    },
    "typography": {
      "lineHeight": "var(--wp--custom--line-height--body)"
    },
    "elements": {
      "link": {
        "color": { "text": "var(--wp--preset--color--brand)" },
        ":hover": { "typography": { "textDecoration": "none" } }
      }
    },
    "blocks": {
      "core/quote": {
        "typography": { "fontStyle": "italic" },
        "spacing": { "padding": { "left": "var(--wp--preset--spacing--40)" } }
      }
    }
  }
}

Die Werte auf der Wurzelebene von styles landen auf dem Body. elements deckt HTML-Grundbausteine ab, die keine Blöcke sind – Link, Button, Überschriften, Bildunterschrift. blocks zielt über den Namen auf einen bestimmten Blocktyp.

Die ehrliche Einschränkung: styles kann nicht alles ausdrücken, was CSS kann. Eigene Media Queries sind nicht vorgesehen, komplexe Selektoren ebenso wenig, Animationen gar nicht, und von den Pseudoklassen wird nur eine kleine Auswahl unterstützt. Fluide Typografie und layoutbasierte Größen decken vieles ab, wofür früher Breakpoints nötig waren – aber eben nicht alles. Die meisten ausgelieferten Block-Themes bringen theme.json plus ein überschaubares Stylesheet mit, und das ist ein normales Ergebnis, kein Scheitern.

Die Falle settings gegen styles

Die mit Abstand häufigste Supportfrage ist eine Variante von „Ich habe meine Markenfarbe eingetragen und es hat sich nichts geändert.”

Richtig. Der Eintrag in settings.color.palette hat --wp--preset--color--brand und ein Farbfeld erzeugt. Angewendet wurde nichts. Damit die Farbe zur Standard-Linkfarbe wird, muss sie zusätzlich unter styles stehen:

{
  "settings": {
    "color": {
      "palette": [{ "slug": "brand", "color": "#1f4ed8", "name": "Brand" }]
    }
  },
  "styles": {
    "elements": {
      "link": { "color": { "text": "var(--wp--preset--color--brand)" } }
    }
  }
}

Merken lässt es sich so: settings ist der Farbkasten, den Sie den Benutzern in die Hand drücken. styles ist der Anstrich, den Sie auftragen, bevor die Benutzer eintreffen.

Die Kaskade, von unten nach oben

Dieser Abschnitt erklärt, warum eine Website die Theme-Datei scheinbar „ignoriert”. WordPress führt mehrere Ebenen zusammen, bevor CSS ausgegeben wird:

  1. Standardwerte des WordPress-Cores – der Core bringt eine eigene theme.json mit Basispalette, Schriftgrößen und Abstandsskala mit.
  2. theme.json des Eltern-Themes
  3. theme.json des Child-Themes – wird Schlüssel für Schlüssel über das Eltern-Theme gelegt, ersetzt also nicht die gesamte Datei.
  4. In der Datenbank gespeicherte Global Styles – das, was das Styles-Panel im Site-Editor schreibt.
  5. Styles an einzelnen Blöcken – Attribute, die im Beitragsinhalt gespeichert und als Inline-Styles oder Klassen ausgegeben werden.

Ebene 4 ist diejenige, die Websites aus dem Tritt bringt. Sobald irgendjemand das Styles-Panel öffnet und speichert, legt WordPress einen Global-Styles-Datensatz an, und dieser Datensatz gewinnt für jede darin enthaltene Eigenschaft gegen Ihre Datei. Spätere Änderungen an theme.json bewirken für diese Eigenschaften nichts Sichtbares – die Website sieht nach dem Deployment exakt gleich aus, obwohl die Datei auf der Festplatte erkennbar anders ist.

Die Lösung besteht darin, den gespeicherten Datensatz zu löschen, und nicht darin, mit !important nachzulegen. Öffnen Sie den Site-Editor, gehen Sie zu Styles, öffnen Sie das Revisionen-Panel und setzen Sie auf die Standardwerte des Themes zurück. Klären Sie das vorher mit Kunde oder Websitebetreiber ab – beim Zurücksetzen gehen deren Anpassungen verloren, und das ist ein echter Verlust, kein Nebeneffekt zum Nulltarif.

Der zweite Verdächtige ist das Caching. WordPress hält die geparsten theme.json-Daten im Cache, statt die Datei bei jedem Request neu einzulesen. Im Produktivbetrieb ist das genau richtig, während der Entwicklung genau falsch. Mit aktiviertem WP_DEBUG – oder in neueren Ausgaben mit der Einstellung für den Theme-Entwicklungsmodus – liest WordPress die Datei jedes Mal neu ein. Wenn Ihre Änderungen erst nach einem Deployment oder einem Cache-Leeren sichtbar werden, sehen Sie genau diesen Effekt.

templateParts und customTemplates

Beides sind Arrays, die Dateien beschreiben, die bereits in Ihrem Theme liegen.

{
  "templateParts": [
    { "name": "header", "title": "Header", "area": "header" },
    { "name": "footer", "title": "Footer", "area": "footer" }
  ],
  "customTemplates": [
    { "name": "page-wide", "title": "Wide Page", "postTypes": ["page"] }
  ]
}

name entspricht dem Dateinamen ohne Endung – parts/header.html, templates/page-wide.html. Der Wert von area ist relevant: Er entscheidet, ob der Teil in ein Header- oder Footer-Landmark-Element eingefasst wird und wie der Editor ihn einsortiert. Lassen Sie ihn weg, gilt der Teil als nicht kategorisiert.

customTemplates sorgt dafür, dass ein Template im Template-Auswahlmenü des Beitragseditors auftaucht. Ohne diesen Eintrag existiert die Datei zwar, ist aber für niemanden auswählbar.

Eine schnelle Diagnosereihenfolge

Wenn ein Block-Theme nicht so gestaltet, wie es die Datei vorgibt, arbeiten Sie das hier ab, bevor Sie irgendetwas anfassen:

  1. Sehen Sie in den Quelltext und suchen Sie den erzeugten Global-Styles-Block. Fehlt Ihre Variable dort, liegt das Problem in settings oder an einem Tippfehler im Slug.
  2. Existiert die Variable, wird aber nicht verwendet, fehlt ein Eintrag unter styles.
  3. Sind beide vorhanden und wird trotzdem etwas überschrieben, prüfen Sie, ob ein Global-Styles-Datensatz gespeichert ist.
  4. Erst danach sehen Sie sich Ihr eigenes Stylesheet, Plugins oder einen Page-Builder an, der CSS später in der Kaskade einschleust.

FAQ

Fragen

Was ist theme.json in WordPress?

Eine einzelne JSON-Konfigurationsdatei im Wurzelverzeichnis eines Block-Themes. Sie steuert zwei Dinge: welche Gestaltungsoptionen der Block-Editor den Benutzern anbietet und wie die Standard-Styles aussehen. WordPress liest die Datei ein, erzeugt daraus CSS-Custom-Properties und ein Stylesheet und führt das Ergebnis mit den Core-Standardwerten und den gespeicherten Global Styles zusammen.

Was ist der Unterschied zwischen settings und styles in theme.json?

settings legt fest, was zur Verfügung steht: Es erzeugt CSS-Variablen und Bedienelemente im Editor, wendet aber von sich aus nichts an. styles weist die Werte tatsächlich zu und greift dabei auf diese Variablen zurück. Eine neue Farbe in der Palette verändert also kein einziges Element, solange Sie sie nicht zusätzlich unter styles referenzieren oder jemand sie im Editor auswählt.

Warum wirken sich meine Änderungen an theme.json im Frontend nicht aus?

Fast immer, weil in der Datenbank gespeicherte Global Styles die Datei überstimmen. Sobald jemand das Styles-Panel im Site-Editor anfasst, gewinnt dieser gespeicherte Datensatz für jede Eigenschaft, die er enthält. Öffnen Sie Styles, setzen Sie über das Revisionen-Panel auf die Theme-Standardwerte zurück und laden Sie die Seite neu. Der zweite Verdächtige ist das Caching der geparsten theme.json-Daten.

Brauche ich zusätzlich zu theme.json noch eine style.css?

Ja. WordPress benötigt style.css für den Theme-Header-Kommentar mit Theme-Name, Version und weiteren Metadaten – sonst wird das Theme überhaupt nicht erkannt. Ansonsten darf die Datei leer bleiben: Ihre Gestaltungsentscheidungen gehören in theme.json, ergänzt um etwas CSS für alles, was theme.json nicht ausdrücken kann.

Welche Versionsnummer gehört in theme.json?

Die höchste Version, die Ihre minimal unterstützte WordPress-Ausgabe versteht. Der Schlüssel version teilt WordPress mit, nach welchem Schema geparst werden soll, und ältere WordPress-Versionen ignorieren Schlüssel, die sie nicht kennen. Wenn Sie ältere Installationen bedienen, bleiben Sie bei deren Version, statt darauf zu hoffen, dass neuere Schlüssel sauber ausfallen.

Ersetzt theme.json CSS vollständig?

Nein. Presets, Block-Standardwerte, Element-Styles, Layout-Breiten und Abstände deckt die Datei gut ab. Eigene Media Queries, komplexe Selektoren, Animationen oder Pseudoklassen jenseits der wenigen unterstützten Zustände kennt sie dagegen nicht. Die meisten produktiven Block-Themes liefern deshalb theme.json plus ein überschaubares Stylesheet aus.