Перейти к содержимому
Шаблоны

theme.json в WordPress: settings, styles и порядок каскада

Разбираем, чем settings отличается от styles в theme.json, и почему правки блочной темы не дают результата — вплоть до каскада, который всё решает.

Опубликовано

theme.json — один файл конфигурации в корне блочной темы, который выполняет две разные задачи: settings определяет, что блочный редактор предлагает пользователю, а styles определяет, как сайт выглядит по умолчанию. WordPress разбирает файл, объединяет его со своими значениями и со всем, что сохранено в редакторе сайта, и выводит результат в виде CSS-переменных и встроенной таблицы стилей на каждой странице.

Именно смешение этих двух задач — причина, по которой правки в theme.json чаще всего «не работают». Объявленный в settings цвет нигде не применяется. Он лишь создаёт переменную и образец в боковой панели редактора.

Ключи верхнего уровня

Минимальный файл выглядит так:

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {},
  "styles": {},
  "templateParts": [],
  "customTemplates": []
}
КлючЗа что отвечает
$schemaТолько автодополнение и проверка в редакторе кода. WordPress его игнорирует.
versionУказывает WordPress, по какой схеме разбирать файл. Это не версия темы.
settingsСоздаёт CSS-переменные и определяет, что доступно в редакторе.
stylesПрименяет реальное оформление по умолчанию.
templatePartsОписывает части в parts/ и область, к которой они относятся.
customTemplatesРегистрирует шаблоны из templates/ для редактора записей.

С version путаются потому, что он выглядит как номер версии темы. Это не так. Он выбирает режим разбора, а старые релизы WordPress молча пропускают ключи из незнакомой им схемы. Поддерживаете старые установки — ориентируйтесь на ту версию, которую они понимают, а не надейтесь, что новые ключи как-нибудь отработают. На момент написания актуальна версия 3; версия 2 по-прежнему широко используется и разбирается корректно.

$schema указывает на URL схемы, размещённой WordPress. Ссылка на trunk даёт самые свежие подсказки в редакторе кода; версионный URL надёжнее, если вы намеренно остаётесь на старой схеме.

settings: что доступно в редакторе

Всё, что находится в settings, превращается в CSS-переменную и, как правило, в элемент управления в редакторе. Само по себе ничто из settings ничего не оформляет.

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

Отсюда получаются переменные, имена которых собираются из пути пресета и слага:

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

Плюс утилитарные классы вроде .has-brand-color и .has-brand-background-color — именно ими редактор применяет выбранный образец к блоку.

Строка "custom": false — вторая половина работы settings: отключение опций. Поставьте её, и произвольный выбор цвета исчезнет, у пользователя останется только ваша палитра. Тот же приём работает повсеместно — settings.typography.customFontSize, settings.spacing.customSpacingSize, settings.border и так далее. В settings нет декоративных ключей: каждый либо добавляет переменную, либо добавляет элемент управления, либо его убирает.

settings.custom — свободный раздел для ваших собственных переменных:

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

Отсюда получаются --wp--custom--line-height--body и --wp--custom--shadow--card. Обратите внимание на преобразование: camelCase разбивается через дефис, а вложенность склеивается двойным дефисом. Ошибка в имени переменной — частая причина того, что значение молча откатывается к запасному.

Настройки можно задавать для отдельных блоков — так разрешают выбор цвета на кнопках, но запрещают на абзацах:

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

styles: то, что реально отрисовывается

styles — раздел, где значения действительно применяются. Его структура повторяет структуру редактора: корневой уровень, затем elements, затем 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)" } }
      }
    }
  }
}

Значения корневого уровня styles попадают на body. elements покрывает HTML-примитивы, которые не являются блоками, — ссылку, кнопку, заголовки, подпись. blocks нацеливается на конкретный тип блока по имени.

Честное ограничение: через styles нельзя выразить всё то, что умеет CSS. Свои медиазапросы написать невозможно, сложных селекторов нет, анимаций нет, а из псевдоклассов поддерживается лишь несколько. Плавная типографика и размеры на основе макета закрывают многое из того, ради чего раньше писали брейкпоинты, но не всё. Большинство рабочих блочных тем несут theme.json и небольшую таблицу стилей рядом — это нормальный результат, а не провал.

Ловушка «settings против styles»

Самый частый вопрос в поддержку звучит примерно так: «Я добавил фирменный цвет, и ничего не изменилось».

Всё верно. Добавление в settings.color.palette создало --wp--preset--color--brand и образец в палитре. Применилось при этом ничего. Чтобы цвет стал цветом ссылок по умолчанию, его нужно прописать ещё и в styles:

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

Понимать это стоит так: settings — набор красок, который вы вручаете пользователю, styles — слой краски, который вы наносите до его прихода.

Каскад, снизу вверх

Именно эта часть объясняет, почему сайт «не замечает» файл темы. Перед выводом CSS WordPress объединяет несколько слоёв:

  1. Значения по умолчанию ядра WordPress — у ядра есть собственный theme.json с базовой палитрой, размерами шрифтов и шкалой отступов.
  2. theme.json родительской темы
  3. theme.json дочерней темы — накладывается на родительский ключ за ключом, а не заменяет файл целиком.
  4. Глобальные стили, сохранённые в базе данных — то, что записывает панель «Стили» в редакторе сайта.
  5. Стили отдельных блоков — атрибуты в содержимом записи, отрисованные как инлайновые стили или классы.

Ломает сайты именно четвёртый слой. Как только кто-то открыл панель «Стили» и сохранил, WordPress создаёт запись глобальных стилей, и она побеждает ваш файл по всем свойствам, которые в неё попали. Дальнейшие правки theme.json для этих свойств не меняют ничего: после деплоя сайт выглядит абсолютно так же, хотя файл на диске очевидно другой.

Лечится это удалением сохранённой записи, а не эскалацией через !important. Откройте редактор сайта, перейдите в «Стили», раскройте панель ревизий и сбросьте оформление к значениям темы. Сначала согласуйте это с клиентом или владельцем сайта — сброс уничтожает его правки, и это реальная потеря, а не безобидное действие.

Второй подозреваемый — кэширование. WordPress кэширует разобранные данные theme.json, а не перечитывает файл на каждый запрос: в продакшене это ровно то, что нужно, а при разработке — ровно то, что мешает. Включённый WP_DEBUG или режим разработки темы в свежих релизах заставляют WordPress перечитывать файл каждый раз. Если ваши правки появляются только после деплоя или сброса кэша — вы видите именно это.

templateParts и customTemplates

Оба ключа — массивы, описывающие файлы, которые уже лежат в теме.

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

name совпадает с именем файла без расширения — parts/header.html, templates/page-wide.html. Значение area важно: от него зависит, будет ли часть обёрнута в ориентир header или footer и как редактор её категоризирует. Пропустите его — и часть останется без категории.

customTemplates — то, благодаря чему шаблон появляется в выпадающем списке в редакторе записей. Без такой записи файл существует, но выбрать его никто не сможет.

Быстрый порядок диагностики

Если блочная тема оформляется не так, как написано в файле, пройдите этот путь, прежде чем что-то менять:

  1. Посмотрите исходный код страницы и найдите сгенерированный блок глобальных стилей. Нет вашей переменной — проблема в settings или в опечатке в слаге.
  2. Переменная есть, но нигде не используется — не хватает записи в styles.
  3. Есть и то и другое, но что-то их перебивает — ищите сохранённую запись глобальных стилей.
  4. И только потом смотрите свою таблицу стилей, плагины или конструктор страниц, который подмешивает CSS позже по каскаду.

FAQ

Вопросы

Что такое theme.json в WordPress?

Это один файл конфигурации в формате JSON в корне блочной темы, отвечающий за две вещи: какие настройки оформления блочный редактор показывает пользователю и как сайт выглядит по умолчанию. WordPress читает его, генерирует из него CSS-переменные и таблицу стилей, а затем объединяет всё это со своими стандартными значениями и с глобальными стилями, которые сохранил пользователь.

Чем settings отличается от styles в theme.json?

Раздел settings описывает, что доступно: он создаёт CSS-переменные и элементы управления в редакторе, но сам ничего не применяет. Раздел styles применяет конкретные значения, обращаясь к этим переменным. Добавили цвет в палитру — на сайте не изменится ничего, пока вы не пропишете его в styles или пока пользователь не выберет его в редакторе.

Почему правки в theme.json не видны на сайте?

Почти всегда потому, что глобальные стили, сохранённые в базе данных, перекрывают theme.json. Стоит кому-то один раз зайти в панель «Стили» редактора сайта и сохранить изменения — эта запись побеждает по всем свойствам, которые в ней есть. Откройте «Стили», через панель ревизий сбросьте оформление к настройкам темы и перезагрузите страницу. Второй подозреваемый — кэширование разобранных данных theme.json.

Нужен ли файл style.css, если есть theme.json?

Да. WordPress требует style.css ради блока-заголовка с именем темы, версией и остальными метаданными — без него тема вообще не будет распознана. Всё остальное содержимое можно оставить пустым и держать оформление в theme.json либо добавить немного CSS для того, что через theme.json выразить нельзя.

Какую версию указывать в theme.json?

Самую свежую из тех, которые понимает минимальная поддерживаемая вами версия WordPress. Ключ version сообщает WordPress, по какой схеме разбирать файл, а старые релизы просто игнорируют незнакомые ключи. Если вы поддерживаете старые установки, оставайтесь на той версии схемы, которую они знают, и не рассчитывайте, что новые ключи отработают хоть как-то.

Заменяет ли theme.json обычный CSS?

Нет. Он хорошо закрывает пресеты, значения по умолчанию для блоков, стили элементов, ширины макета и отступы, но в нём нет собственных медиазапросов, сложных селекторов, анимаций и почти всех псевдоклассов. Большинство продакшен-тем на блоках поставляются с theme.json плюс небольшой таблицей стилей.