Перейти к содержимому

theme.json — основа дизайн-системы WordPress и WooCommerce

theme.json — центральный конфигурационный файл блочной темы WordPress. Единая точка, через которую задаются все визуальные настройки сайта: цвета, типографика, отступы, скругления, градиенты, тени и поведение блоков. Для сайтов на WordPress и WooCommerce theme.json — это фундамент дизайн-системы.

Почему theme.json критичен для магазина на WooCommerce:

  • Единый источник стилей для страниц каталога, товаров, корзины и оформления заказа
  • Гарантия консистентности между контентными страницами и страницами магазина
  • Возможность заблокировать произвольные цвета/шрифты у контент-менеджеров, сохранив бренд
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": true,
"layout": { },
"color": { },
"typography": { },
"spacing": { },
"border": { },
"shadow": { },
"custom": { },
"blocks": { }
},
"styles": {
"color": { },
"typography": { },
"spacing": { },
"elements": {
"heading": { },
"button": { },
"link": { }
},
"blocks": { }
},
"templateParts": [ ],
"customTemplates": [ ]
}
СекцияНазначение
settingsКакие элементы управления доступны в редакторе (палитра, размеры шрифтов, spacing scale)
stylesЗначения по умолчанию: цвета фона/текста, типографика, отступы
settings.customКастомные design tokens — произвольные переменные, доступные как CSS custom properties
templatePartsШаблонные части темы (header, footer, sidebar)
customTemplatesПользовательские шаблоны, регистрируемые темой

settings.custom — главный механизм хранения дизайн-токенов в WordPress. Все значения, определённые здесь, автоматически становятся CSS-переменными.

Три слоя токенов (по W3C DTCG):

СлойОписаниеПример
Option tokens (primitive)Сырая палитра, базовые значенияblue-500: #78bbfa
Decision tokens (semantic)Как и где применятьcolor-accent: {color.option.blue-900}
Component tokensКонтекст для конкретных компонентовbutton-primary-bg: {color.decision.accent}
{
"settings": {
"custom": {
"brand": {
"primary": "#2563EB",
"secondary": "#7C3AED",
"accent": "#F59E0B"
},
"text": {
"primary": "#111827",
"secondary": "#6B7280",
"inverse": "#FFFFFF"
},
"spacing": {
"xs": "4px",
"sm": "8px",
"md": "16px",
"lg": "24px",
"xl": "32px",
"2xl": "48px"
},
"border": {
"radius": {
"sm": "4px",
"md": "8px",
"lg": "16px"
}
},
"typography": {
"fontSize": {
"sm": "0.875rem",
"base": "1rem",
"lg": "1.125rem",
"xl": "1.25rem",
"2xl": "1.5rem",
"3xl": "2rem"
}
},
"woocommerce": {
"saleBadge": "#EF4444",
"stockBadge": "#10B981",
"ratingStar": "#F59E0B",
"priceColor": "#111827",
"salePriceColor": "#EF4444"
}
}
}
}

WordPress автоматически генерирует CSS-переменные:

Путь в theme.jsonCSS-переменная
settings.custom.brand.primary--wp--custom--brand--primary
settings.custom.spacing.lg--wp--custom--spacing--lg
settings.custom.woocommerce.saleBadge--wp--custom--woocommerce--sale-badge

Схема: --wp--custom--<путь через двойное тире> — camelCase ключи превращаются в kebab-case.

Токены из custom можно использовать в секции styles напрямую:

{
"styles": {
"color": {
"text": "var(--wp--custom--text--primary)",
"background": "var(--wp--custom--brand--secondary)"
},
"elements": {
"heading": {
"color": {
"text": "var(--wp--custom--text--primary)"
}
},
"button": {
"color": {
"text": "var(--wp--custom--text--inverse)",
"background": "var(--wp--custom--brand--primary)"
},
"border": {
"radius": "var(--wp--custom--border--radius--md)"
}
}
}
}
}

Минимальный набор цветов для WordPress/WooCommerce:

{
"settings": {
"custom": {
"palette": {
"primary": {
"50": "#EFF6FF",
"500": "#3B82F6",
"900": "#1E3A5F"
},
"neutral": {
"50": "#F9FAFB",
"900": "#111827"
},
"feedback": {
"success": "#10B981",
"warning": "#F59E0B",
"error": "#EF4444",
"info": "#3B82F6"
}
}
}
}
}

Требования WCAG AA:

  • Основной текст на фоне: контраст ≥ 4.5:1
  • Крупный текст (≥ 18px bold): контраст ≥ 3:1
  • Интерактивные элементы: контраст ≥ 3:1

Градиенты задаются в styles.color.gradient:

{
"styles": {
"color": {
"gradient": "linear-gradient(135deg, var(--wp--custom--palette--primary--500), var(--wp--custom--palette--primary--900))"
}
}
}
{
"settings": {
"custom": {
"typography": {
"heading": {
"fontFamily": "'Inter', sans-serif",
"fontWeight": "700",
"lineHeight": "1.2"
},
"body": {
"fontFamily": "'Inter', sans-serif",
"fontWeight": "400",
"lineHeight": "1.6"
}
},
"fontSize": {
"scale": {
"sm": "0.875rem",
"base": "1rem",
"lg": "1.125rem",
"xl": "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
"4xl": "2.25rem"
}
}
}
}
}

Рекомендации:

  • Используйте rem (16px = 1rem) — масштабируемость
  • Адаптивная типографика через clamp() или медиа-запросы
  • RTL/LTR поддерживается WordPress автоматически

Два подхода:

Мультипликативная: 0, 0.13, 0.25, 0.5, 1, 2, 4, 8 rem

Аддитивная: 0, 1, 3, 5, 7, 9, 11, 13 rem

В WordPress — через settings.spacing.spacingScale:

{
"settings": {
"spacing": {
"spacingScale": {
"steps": 7,
"operator": "*",
"increment": 1.5
}
}
}
}

Настройка скруглений в theme.json прошла два этапа:

До WordPress 6.9: через settings.custom и прямые значения

Заголовок раздела «До WordPress 6.9: через settings.custom и прямые значения»

До версии 6.9 скругления задавались либо как кастомные токены в settings.custom, либо как прямые значения в styles:

{
"settings": {
"custom": {
"border": {
"radius": {
"sm": "4px",
"md": "8px",
"lg": "16px"
}
}
}
},
"styles": {
"elements": {
"button": {
"border": {
"radius": "var(--wp--custom--border--radius--md)"
}
}
}
}
}

Минусы старого подхода:

  • Нет UI-интерфейса для выбора из пресетов в редакторе
  • Контент-редактор не мог выбрать скругление через панель Styles
  • Требовалось ручное прописывание CSS-переменных в каждом блоке

Начиная с WP 6.9, появились border radius size presets — массив размеров скруглений, из которых пользователь выбирает в интерфейсе редактора.

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"border": {
"radius": true,
"radiusSizes": [
{
"name": "XS",
"slug": "xs",
"size": "0.125rem"
},
{
"name": "Small",
"slug": "sm",
"size": "0.25rem"
},
{
"name": "Medium",
"slug": "md",
"size": "0.5rem"
},
{
"name": "Large",
"slug": "lg",
"size": "1rem"
},
{
"name": "XL",
"slug": "xl",
"size": "1.5rem"
}
]
}
}
}

Каждый объект размера:

ПолеОписание
nameЧеловекочитаемое название («XS», «Small»)
slugМашинное имя → CSS-переменная --wp--preset--border-radius--{slug}
sizeCSS-значение размера

Совет: используйте t-shirt sizing (XS, SM, MD, LG, XL, 2XL, 3XL) когда пресеты масштабируются от меньшего к большему.

UI-поведение: если задано ≤ 7 пресетов — отображается range slider; если > 7 — select dropdown.

WordPress автоматически генерирует CSS custom properties:

:root {
--wp--preset--border-radius--xs: 0.125rem;
--wp--preset--border-radius--sm: 0.25rem;
--wp--preset--border-radius--md: 0.5rem;
--wp--preset--border-radius--lg: 1rem;
--wp--preset--border-radius--xl: 1.5rem;
}
{
"styles": {
"blocks": {
"core/image": {
"border": {
"radius": {
"topLeft": "0px",
"topRight": "var(--wp--preset--border-radius--xl)",
"bottomLeft": "var(--wp--preset--border-radius--xl)",
"bottomRight": "0px"
}
}
},
"woocommerce/product-button": {
"border": {
"radius": "var(--wp--preset--border-radius--md)"
}
}
}
}
}

Можно использовать двухзначный синтаксис для эллиптических скруглений:

{
"name": "Drawn 1",
"slug": "drawn-1",
"size": "15px 255px"
}

Важно: border-radius shorthand (например 255px 15px 225px 15px/15px 225px 15px 255px) не работает — пресеты применяются к отдельным углам. Для hand-drawn эффекта создавайте block style variations с заранее применёнными радиусами.

  • Значения с (, ), var(...), clamp(...), calc(...)не работают в radiusSizes
  • В отличие от других пресетов (цвета, шрифты), у radiusSizes нет свойства customSettingName для отключения произвольных значений
  • Единственный способ скрыть border radius из UI: settings.border.radius: false (отключает и пресеты тоже)

Оба ограничения обсуждаются в Gutenberg issue #49504.

АспектДо 6.9WP 6.9+
Где задаютсяsettings.custom или прямой CSSsettings.border.radiusSizes
CSS-переменные--wp--custom--border--radius--*--wp--preset--border-radius--*
UI-выборНетRange slider / dropdown
Ограничения на значенияЛюбые CSS-значенияБез скобок и функций
РекомендацияУстаревший подход для border radiusСтандарт для новых тем

При разработке интернет-магазина theme.json должен учитывать блоки WooCommerce:

{
"styles": {
"blocks": {
"woocommerce/product-price": {
"color": {
"text": "var(--wp--custom--woocommerce--price-color)"
},
"typography": {
"fontSize": "var(--wp--custom--typography--font-size--xl)",
"fontWeight": "700"
}
},
"woocommerce/product-button": {
"color": {
"text": "var(--wp--custom--text--inverse)",
"background": "var(--wp--custom--brand--primary)"
},
"border": {
"radius": "var(--wp--custom--border--radius--md)"
}
},
"woocommerce/product-sale-badge": {
"color": {
"text": "#FFFFFF",
"background": "var(--wp--custom--woocommerce--sale-badge)"
}
}
}
}
}
{
"settings": {
"blocks": {
"woocommerce/product-collection": {
"spacing": {
"blockGap": "var(--wp--custom--spacing--lg)"
}
},
"woocommerce/mini-cart": {
"typography": {
"fontSize": "var(--wp--custom--typography--font-size--sm)"
}
}
}
}
}
  1. Выделите WooCommerce-токены в отдельную группу custom.woocommerce — sale badge, stock status, цены, рейтинг
  2. Используйте settings.blocks для контроля доступных настроек в WooCommerce-блоках
  3. Задайте стили по умолчанию для товарной сетки через styles.blocks["woocommerce/product-collection"]
  4. Помните о странице оформления заказа — стили из theme.json применяются и к Checkout-блоку
  5. Цены должны выделяться типографически — крупнее и жирнее основного текста
{
"settings": {
"custom": {
"woocommerce": {
"saleBadge": "#EF4444",
"saleBadgeText": "#FFFFFF",
"stockInStock": "#10B981",
"stockOutOfStock": "#EF4444",
"stockLowStock": "#F59E0B",
"ratingStar": "#F59E0B",
"ratingStarEmpty": "#D1D5DB",
"price": "#111827",
"salePrice": "#EF4444",
"buttonAddToCart": "#2563EB",
"buttonAddToCartHover": "#1D4ED8"
}
}
}
}

Глобально заблокировать все элементы управления, затем выборочно включить нужные. Критично для WooCommerce-сайтов, где контент-менеджеры работают с товарами:

{
"settings": {
"appearanceTools": false,
"border": {
"color": false,
"radius": false,
"style": false,
"width": false
},
"color": {
"text": false,
"background": false,
"link": false,
"custom": false
},
"spacing": {
"margin": false,
"padding": false
},
"typography": {
"customFontSize": false,
"fontStyle": false,
"fontWeight": false
},
"blocks": {
"core/button": {
"color": {
"text": true,
"background": true
}
},
"woocommerce/product-button": {
"color": {
"text": true,
"background": true
}
}
}
}
}

Это гарантирует, что ни контент-редакторы, ни менеджеры товаров не нарушат дизайн-систему произвольными цветами и отступами.

theme.json — не изолированный файл. Он работает в связке:

ИнструментСвязь с theme.json
Figma + Tokens StudioЭкспорт токенов → theme.json через vip-design-system-bridge
Tailwind CSSСинхронизация токенов theme.jsontailwind.config через CSS-переменные
daisyUIТемы daisyUI маппятся на WordPress-палитру из theme.json
DESIGN.mdAI-читаемый контракт дизайна, из которого генерируется theme.json
Style DictionaryТрансформация W3C DTCG-токенов в --wp--custom--*
  1. settings.custom — единый source of truth для всех дизайн-токенов
  2. Используйте сгенерированные CSS-переменные везде — не дублируйте значения в CSS
  3. Группируйте WooCommerce-токены отдельноcustom.woocommerce.*
  4. Lock down для контент-менеджеров — оставьте им только нужные настройки
  5. Стилизуйте WooCommerce-блоки явно в styles.blocks — не полагайтесь на дефолтные стили плагина
  6. Поддерживайте контрастность WCAG AA для всех цветов, включая цены и бейджи распродаж
  7. Версионируйте theme.json в Git — это код, а не просто конфиг