Saltar al contenido
Temas

theme.json en WordPress: settings, styles y la cascada

Entiende por qué settings y styles hacen trabajos distintos en theme.json y arregla los cambios de tema de bloques que no renderizan nada recorriendo la cascada de WordPress.

Publicada

theme.json es un único archivo de configuración en la raíz de un tema de bloques que hace dos trabajos separados: settings decide qué ofrece el editor de bloques al usuario y styles decide qué aspecto tiene el sitio por defecto. WordPress lo analiza, lo combina con sus propios valores por defecto y con lo que se haya guardado en el editor del sitio, y devuelve el resultado como propiedades personalizadas CSS más una hoja de estilos en línea en cada página.

Confundir esos dos trabajos es la razón por la que la mayoría de las ediciones de theme.json parecen no hacer nada. Declarar un color en settings no aplica ese color en ninguna parte. Solo crea una variable y una muestra de color en la barra lateral del editor.

Las claves de primer nivel

Un archivo mínimo se ve así:

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {},
  "styles": {},
  "templateParts": [],
  "customTemplates": []
}
ClaveQué hace
$schemaSolo autocompletado y validación en el editor de código. WordPress la ignora.
versionLe dice a WordPress qué forma de esquema analizar. No es la versión de tu tema.
settingsGenera variables CSS y controla qué expone el editor.
stylesAplica el estilo real por defecto.
templatePartsDeclara las partes de parts/ y a qué área pertenecen.
customTemplatesRegistra plantillas de página de templates/ para el editor de entradas.

version despista porque parece el número de versión del tema. No lo es. Selecciona un modo de análisis, y las versiones antiguas de WordPress ignoran en silencio las claves de una forma de esquema que no conocen. Si das soporte a instalaciones antiguas, apunta a la versión que esas instalaciones entienden en lugar de suponer que las claves nuevas degradan con elegancia. La versión 3 es la actual en el momento de escribir esto; la versión 2 sigue muy desplegada y se sigue analizando.

$schema apunta a una URL de esquema alojada por WordPress. Fijarla en trunk te da las sugerencias más recientes en tu editor de código; una URL de versión concreta es más segura si te estás quedando deliberadamente en un esquema antiguo.

settings: lo que ofrece el editor

Todo lo que hay bajo settings produce una propiedad personalizada CSS y, en la mayoría de los casos, un control en el editor. Nada de lo que hay bajo settings da estilo a nada.

{
  "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"
    }
  }
}

Eso produce variables nombradas a partir de la ruta del preset y del slug:

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

También produce clases de utilidad como .has-brand-color y .has-brand-background-color, que es como el editor aplica a un bloque la muestra elegida.

La línea "custom": false es la otra mitad de settings: desactivar opciones. Ponla y el selector de color libre desaparece, dejando al usuario tu paleta y nada más. El mismo patrón funciona en todas partes: settings.typography.customFontSize, settings.spacing.customSpacingSize, settings.border, y así con el resto. Nada de lo que hay bajo settings es decorativo; cada clave añade una variable, añade un control o quita un control.

settings.custom es un cajón libre para tus propias variables:

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

Esos pasan a ser --wp--custom--line-height--body y --wp--custom--shadow--card. Fíjate en la transformación: las claves en camelCase se parten en kebab-case y el anidamiento se une con doble guion. Equivocarse en el nombre de una variable es un motivo habitual de que un valor caiga en silencio a su valor de respaldo.

Puedes limitar los settings por bloque, que es como permites un selector de color en los botones pero no en los párrafos:

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

styles: lo que realmente se renderiza

styles es donde los valores se aplican. Refleja la estructura del editor: un nivel raíz, luego elements y luego 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)" } }
      }
    }
  }
}

Los styles de nivel raíz aterrizan en el body. elements cubre las primitivas HTML que no son bloques: enlace, botón, encabezados, leyenda. blocks apunta a un tipo de bloque concreto por su nombre.

La limitación honesta: styles no puede expresar todo lo que puede el CSS. No hay forma de escribir tus propias media queries, ni selectores complejos, ni animaciones, y solo hay un conjunto pequeño de estados de pseudoclase soportados. La tipografía fluida y el dimensionado basado en el layout cubren buena parte de aquello para lo que antes se usaban breakpoints, pero no todo. La mayoría de los temas de bloques que se publican llevan theme.json más una hoja de estilos modesta, y eso es un resultado normal, no un fracaso.

La trampa de settings frente a styles

La consulta de soporte más habitual es alguna variante de “añadí el color de mi marca y no cambió nada”.

Correcto. Añadirlo a settings.color.palette creó --wp--preset--color--brand y una muestra. No aplicó nada. Para que sea el color de enlace por defecto tienes que escribirlo también bajo styles:

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

Léelo así: settings es la caja de pintura que le entregas al usuario, styles es la mano de pintura que das antes de que llegue.

La cascada, de menor a mayor prioridad

Esta es la parte que explica un sitio que “ignora” el archivo del tema. WordPress combina varias capas antes de emitir el CSS:

  1. Valores por defecto del núcleo de WordPress: el núcleo incluye su propio theme.json con una paleta base, tamaños de fuente y una escala de espaciado.
  2. theme.json del tema padre
  3. theme.json del tema hijo: se combina sobre el padre clave por clave, no reemplaza el archivo entero.
  4. Estilos globales guardados en la base de datos: lo que escribe el panel Estilos del editor del sitio.
  5. Estilos por bloque en bloques individuales: atributos guardados en el contenido de la entrada, renderizados como estilos en línea o clases.

La capa 4 es la que rompe sitios. En cuanto alguien abre el panel Estilos y guarda, WordPress almacena un registro de estilos globales y ese registro gana sobre tu archivo para todas las propiedades que contiene. Editar theme.json después no cambia nada visible para esas propiedades, en un sitio que se ve idéntico tras un despliegue mientras el archivo en disco es claramente distinto.

La solución es borrar el registro guardado, no escalar con !important. Abre el editor del sitio, ve a Estilos, abre el panel de revisiones y restablece los valores por defecto del tema. Confírmalo antes con el cliente o el dueño del sitio: restablecer descarta sus personalizaciones, lo cual es un coste real, no una acción gratuita.

El segundo sospechoso es el caché. WordPress cachea los datos analizados de theme.json en lugar de releer el archivo en cada petición, que es exactamente lo que quieres en producción y exactamente lo que no quieres mientras desarrollas. Activar WP_DEBUG, o el ajuste de modo de desarrollo de tema en versiones recientes, hace que WordPress relea el archivo cada vez. Si tus cambios solo aparecen tras un despliegue o un vaciado de caché, eso es lo que estás viendo.

templateParts y customTemplates

Ambas son arrays que describen archivos que ya están en tu tema.

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

name coincide con el nombre del archivo sin su extensión: parts/header.html, templates/page-wide.html. El valor de area importa: decide si la parte se envuelve en un elemento de referencia de cabecera o pie y cómo la clasifica el editor. Si lo omites, la parte se trata como sin clasificar.

customTemplates es lo que hace que una plantilla aparezca en el desplegable de plantillas del editor de entradas. Sin esa entrada, el archivo existe pero nadie puede seleccionarlo.

Un orden rápido de diagnóstico

Cuando un tema de bloques no aplica el estilo que dice el archivo, recorre esto antes de tocar nada:

  1. Mira el código fuente y busca el bloque de estilos globales generado. Si tu variable no está ahí, el problema está en settings o en un slug mal escrito.
  2. Si la variable existe pero no se usa, el problema es una entrada de styles que falta.
  3. Si existen ambas pero algo las sobrescribe, busca un registro guardado de estilos globales.
  4. Solo entonces mira tu propia hoja de estilos, los plugins o un maquetador visual que inyecte CSS más tarde en la cascada.

FAQ

Preguntas

¿Qué es theme.json en WordPress?

Es un único archivo de configuración JSON en la raíz de un tema de bloques que controla dos cosas: qué opciones de diseño ofrece el editor de bloques al usuario y cuáles son los estilos por defecto. WordPress lo lee, genera propiedades personalizadas CSS y una hoja de estilos a partir de él, y lo combina con los valores por defecto del núcleo y con los estilos globales que haya guardado el usuario.

¿Cuál es la diferencia entre settings y styles en theme.json?

Settings define qué está disponible y genera variables CSS más los controles del editor, pero por sí solo no aplica nada. Styles aplica valores reales usando esas variables. Añadir un color a la paleta no cambia ningún elemento hasta que lo referencias también en styles o hasta que alguien lo elige en el editor.

¿Por qué mis cambios en theme.json no se ven en la parte pública?

Casi siempre porque los estilos globales guardados en la base de datos tienen prioridad sobre theme.json. En cuanto alguien toca el panel Estilos del editor del sitio, ese registro guardado gana para todas las propiedades que contiene. Abre Estilos, usa el panel de revisiones para restablecer los valores por defecto del tema y recarga. El caché de los datos analizados de theme.json es el segundo sospechoso.

¿Sigo necesitando un archivo style.css si uso theme.json?

Sí. WordPress exige style.css por el comentario de cabecera del tema, que aporta el nombre, la versión y otros metadatos; sin él el tema ni siquiera se reconoce. Puedes dejarlo vacío por lo demás y poner tus decisiones de diseño en theme.json, o mantener algo de CSS para lo que theme.json no puede expresar.

¿Qué número de versión debo poner en theme.json?

Usa la versión más alta que entienda la versión mínima de WordPress a la que das soporte. La clave version le dice a WordPress qué forma de esquema debe analizar, y las versiones antiguas de WordPress ignoran las claves que no reconocen. Si das soporte a instalaciones antiguas, quédate en la versión que esas instalaciones soportan en lugar de suponer que las claves nuevas degradan con elegancia.

¿theme.json sustituye por completo al CSS?

No. Cubre bien los presets, los valores por defecto de los bloques, los estilos de elementos, los anchos de layout y el espaciado, pero no tiene ningún concepto de media queries escritas por ti, selectores complejos, animaciones ni estados de pseudoclase más allá de los pocos que soporta. La mayoría de temas de bloques en producción incluyen theme.json más una hoja de estilos modesta para el resto.