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 объединяет несколько слоёв:
- Значения по умолчанию ядра WordPress — у ядра есть собственный
theme.jsonс базовой палитрой, размерами шрифтов и шкалой отступов. theme.jsonродительской темыtheme.jsonдочерней темы — накладывается на родительский ключ за ключом, а не заменяет файл целиком.- Глобальные стили, сохранённые в базе данных — то, что записывает панель «Стили» в редакторе сайта.
- Стили отдельных блоков — атрибуты в содержимом записи, отрисованные как инлайновые стили или классы.
Ломает сайты именно четвёртый слой. Как только кто-то открыл панель «Стили» и сохранил, 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 — то, благодаря чему шаблон появляется в выпадающем списке в редакторе записей. Без такой записи файл существует, но выбрать его никто не сможет.
Быстрый порядок диагностики
Если блочная тема оформляется не так, как написано в файле, пройдите этот путь, прежде чем что-то менять:
- Посмотрите исходный код страницы и найдите сгенерированный блок глобальных стилей. Нет вашей переменной — проблема в
settingsили в опечатке в слаге. - Переменная есть, но нигде не используется — не хватает записи в
styles. - Есть и то и другое, но что-то их перебивает — ищите сохранённую запись глобальных стилей.
- И только потом смотрите свою таблицу стилей, плагины или конструктор страниц, который подмешивает 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 плюс небольшой таблицей стилей.