Когда клиент или контент-менеджер получает в распоряжение Gutenberg с настройками по умолчанию, сайт неизбежно сталкивается с проблемой, известной в индустрии как «дизайн-анархия»:
Исторически разработчики пытались решить это добавлением десятков разрозненных вызовов в functions.php:
// Устаревший процедурный подход (Legacy WP)
add_theme_support('disable-custom-colors');
add_theme_support('editor-color-palette', [...]);
add_theme_support('disable-custom-font-sizes');Такой подход фрагментировал код, требовал ручной генерации CSS-классов и создавал рассинхронизацию между фронтендом и админкой.
Современный стандарт WordPress (WP 6.6–6.7+) переводит управление редактором на декларативный манифест theme.json v3 и принцип наименьших привилегий (Principle of Least Privilege / POLP).
Манифест theme.json является единым источником истины (Single Source of Truth) для всей дизайн-системы. Он отключает произвольные настройки, генерирует строгий набор CSS Custom Properties (--wp--preset--*) и гарантирует 100% совпадение внешнего вида страницы в редакторе и на публичной части сайта.
Управление стилями и ограничениями в Gutenberg подчиняется строгой 5-уровневой иерархии каскада стилей (Global Styles Cascade):
┌────────────────────────────────────────────────────────────────────────┐
│ 1. БАЗОВАЯ КОНФИГУРАЦИЯ ЯДРА │
│ wp-includes/theme.json │
│ Дефолтные палитры, шрифты и базовые стили тегов WordPress │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 2. КОНФИГУРАЦИЯ РОДИТЕЛЬСКОЙ ТЕМЫ │
│ parent-theme/theme.json │
│ Дизайн-система проекта: токены цветов, типографика, сетка отступов │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 3. ПЕРЕОПРЕДЕЛЕНИЕ ДОЧЕРНЕЙ ТЕМЫ │
│ child-theme/theme.json │
│ Дельта изменений под специфику клиента (переопределяет родителя) │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 4. ПОЛЬЗОВАТЕЛЬСКИЕ НАСТРОЙКИ (DB) │
│ CPT: wp_global_styles │
│ Изменения, сделанные администратором через Редактор стилей (Site Ed.) │
└───────────────────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 5. АТРИБУТЫ КОНКРЕТНОГО БЛОКА │
│ Локальные настройки конкретного экземпляра блока │
└────────────────────────────────────────────────────────────────────────┘theme.json v3#Файл делится на две ключевые секции:
settings (Настройки возможностей редактора):
Определяет, какие панели и контролы видит пользователь в боковой панели. Здесь отключаются произвольные цвета ("custom": false), градиенты ("customGradient": false), настраиваются сетки отступов (spacingScale) и допустимые размеры шрифтов (fontSizes).styles (Глобальные CSS-стили):
Задает правила стилизации для всего сайта, конкретных HTML-элементов (link, button, heading) и блоков ядра (core/quote, core/button). WordPress автоматически компилирует эти правила в чистый CSS.Создание конфигурационного файла в корне темы. Указание схемы $schema для автодополнения и валидации ключей в IDE (VS Code / PHPStorm).
Директива version: 3 обеспечивает поддержку расширенных селекторов и CSS-псевдоклассов (:hover, :focus).
Установка custom: false и customGradient: false. Регистрация фирменных цветов бренда (brand-primary, brand-accent, surface, text).
Ядро автоматически сгенерирует CSS-переменные --wp--preset--color--{slug} и классы .has-{slug}-color.
Отключение произвольного ввода размеров кегля (customFontSize: false). Фиксация шагов отступов (spacingScale) для предотвращения хаотичных паддингов.
Формирует предсказуемую 8-пиксельную сетку дизайна сайта.
Ограничение доступных типов блоков в зависимости от типа записи (post, page, custom post type) через PHP-фильтр с проверкой $editor_context.
Устраняет из палитры авторов тяжелые и опасные блоки (кастомный HTML, embed-виджеты).
Фиксация ключевых блоков посадочных страниц: запрет на удаление и перемещение критических секций (шапка, форма, CTA) через атрибуты lock.
Авторы могут менять только текстовый контент и фото, не нарушая структуру верстки.
Динамическое управление настройками редактора через хук block_editor_settings_all: администраторы сохраняют полный контроль, авторы получают урезанный UI.
Проверка current_user_can('manage_options') на стороне сервера.
Ядро считывает wp-includes/theme.json, затем корневой theme.json темы. Данные мерджатся: настройки темы переопределяют дефолтные параметры ядра.
WordPress формирует тег <style id='wp-block-library-theme-inline-css'>. Все палитры и размеры конвертируются в CSS-переменные --wp--preset--* на селекторе :root.
В админ-панели редактор монтируется внутри <iframe> (API v3). Стили темы и CSS-переменные автоматически инжектируются внутрь iframe, обеспечивая 100% WYSIWYG.
На основе settings.color.custom: false боковая панель инспектора скрывает контрол свободного выбора цвета (Color Picker), оставляя только фирменные кружки брендбука.
Редактор проверяет templateLock='all'. Кнопки удаления блока (Delete) и стрелки перемещения (Move Up/Down) деактивируются в тулбаре для защиты верстки.
Разработчик добавил фильтр allowed_block_types_all, возвращающий массив из 5 базовых блоков, чтобы контент-менеджеры не использовали лишние элементы. Однако после этого в меню «Внешний вид → Редактор сайта (Site Editor)» сломалась возможность редактирования шаблонов и навигации. В чем причина?
Ниже представлен эталонный комплекс тонкой настройки Gutenberg: конфигурация theme.json v3 под корпоративный брендбук, модуль серверных ограничений на PHP 8.2+ и пример неубиваемой залоченной посадочной страницы.
theme.json (Версия 3)#{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": false,
"color": {
"custom": false,
"customGradient": false,
"defaultPalette": false,
"defaultGradients": false,
"palette": [
{
"name": "Основной бренд (Indigo)",
"slug": "brand-primary",
"color": "#4F46E5"
},
{
"name": "Акцентный циан (Cyan)",
"slug": "brand-accent",
"color": "#06B6D4"
},
{
"name": "Глубокий темный (Surface)",
"slug": "surface-dark",
"color": "#0F172A"
},
{
"name": "Мягкий светлый (Surface)",
"slug": "surface-light",
"color": "#F8FAFC"
},
{
"name": "Текст основной",
"slug": "text-primary",
"color": "#1E293B"
},
{
"name": "Текст приглушенный",
"slug": "text-muted",
"color": "#64748B"
}
]
},
"typography": {
"customFontSize": false,
"fontStyle": false,
"fontWeight": true,
"letterSpacing": false,
"textDecoration": false,
"fontSizes": [
{
"name": "Мелкий (Small)",
"slug": "sm",
"size": "0.875rem"
},
{
"name": "Базовый (Base)",
"slug": "base",
"size": "1rem"
},
{
"name": "Средний (Medium)",
"slug": "md",
"size": "1.25rem"
},
{
"name": "Крупный заголовок (Large)",
"slug": "lg",
"size": "1.75rem"
},
{
"name": "Экранный заголовок (Display)",
"slug": "xl",
"size": "2.5rem"
}
]
},
"spacing": {
"customSpacingSize": false,
"spacingScale": {
"operator": "*",
"increment": 1.5,
"steps": 7,
"mediumStep": 3,
"unit": "rem"
},
"units": ["rem", "px", "%"]
},
"layout": {
"contentSize": "840px",
"wideSize": "1280px"
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--surface-light)",
"text": "var(--wp--preset--color--text-primary)"
},
"typography": {
"fontSize": "var(--wp--preset--font-size--base)",
"lineHeight": "1.6"
},
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--brand-primary)"
},
":hover": {
"color": {
"text": "var(--wp--preset--color--brand-accent)"
}
}
},
"heading": {
"color": {
"text": "var(--wp--preset--color--text-primary)"
},
"typography": {
"fontWeight": "700",
"lineHeight": "1.25"
}
},
"button": {
"color": {
"background": "var(--wp--preset--color--brand-primary)",
"text": "#FFFFFF"
},
"border": {
"radius": "8px"
}
}
},
"blocks": {
"core/quote": {
"border": {
"left": {
"color": "var(--wp--preset--color--brand-accent)",
"width": "4px"
}
},
"typography": {
"fontStyle": "italic"
}
}
}
}
}inc/editor-restrictions.php#<?php
/**
* Серверные ограничения редактора: контекстные белые списки и ролевой доступ.
*/
declare(strict_types=1);
namespace AgenticLab\Editor;
use WP_Block_Editor_Context;
defined('ABSPATH') || exit;
/**
* 1. Контекстное ограничение типов блоков (Белый список)
*/
add_filter('allowed_block_types_all', function ($allowed_blocks, WP_Block_Editor_Context $context) {
// В полноэкранном редакторе FSE (Site Editor) разрешаем все блоки ядра
if (empty($context->post)) {
return true;
}
// Для стандартных статей блога (post) разрешаем только чистые контентные блоки
if ($context->post->post_type === 'post') {
return [
'core/paragraph',
'core/heading',
'core/list',
'core/list-item',
'core/image',
'core/quote',
'core/code',
'core/table',
'core/separator',
// Кастомные блоки проекта
'agenticlab/hero-card',
];
}
// Для посадочных страниц (page) добавляем структурные блоки
if ($context->post->post_type === 'page') {
return [
'core/paragraph',
'core/heading',
'core/list',
'core/list-item',
'core/image',
'core/group',
'core/columns',
'core/column',
'core/buttons',
'core/button',
'agenticlab/hero-card',
];
}
return $allowed_blocks;
}, 10, 2);
/**
* 2. Ролевое ограничение возможностей редактора
* Пользователи без прав администратора не видят инструменты кастомизации кода
*/
add_filter('block_editor_settings_all', function (array $editor_settings, WP_Block_Editor_Context $context): array {
if (!current_user_can('manage_options')) {
// Отключаем редактор кода (Code Editor) для контент-менеджеров
$editor_settings['codeEditingEnabled'] = false;
// Запрещаем редактирование стилей блоков через inline CSS
$editor_settings['canUpdateBlockBindings'] = false;
// Отключаем блокировку Openverse (сторонние стоки)
$editor_settings['enableOpenverseMediaCategory'] = false;
}
return $editor_settings;
}, 10, 2);templates/locked-landing.html#Пример разметки шаблона лендинга с блокировкой структуры (templateLock: "all" и гранулярный lock), при котором автор может редактировать только текст, но не может удалить или переместить карточки:
<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"3rem","bottom":"3rem"}}},"layout":{"type":"constrained"},"templateLock":"all"} -->
<div class="wp-block-group alignfull" style="padding-top:3rem;padding-bottom:3rem">
<!-- wp:heading {"textAlign":"center","level":1,"lock":{"move":true,"remove":true}} -->
<h1 class="wp-block-heading has-text-align-center">Инженерный стек разработки</h1>
<!-- /wp:heading -->
<!-- wp:paragraph {"textAlign":"center","lock":{"move":true,"remove":true}} -->
<p class="has-text-align-center">Изучайте проверенные производственные шаблоны проектирования.</p>
<!-- /wp:paragraph -->
<!-- wp:columns {"lock":{"move":true,"remove":true}} -->
<div class="wp-block-columns">
<!-- wp:column {"lock":{"move":true,"remove":true}} -->
<div class="wp-block-column">
<!-- wp:agenticlab/hero-card {"title":"Архитектура Core","badgeText":"PHP 8.2","lock":{"remove":true}} /-->
</div>
<!-- /wp:column -->
<!-- wp:column {"lock":{"move":true,"remove":true}} -->
<div class="wp-block-column">
<!-- wp:agenticlab/hero-card {"title":"Gutenberg React","badgeText":"REACT 19","lock":{"remove":true}} /-->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
</div>
<!-- /wp:group -->Бизнес требует создать шаблон лидогенерирующей страницы, где контент-менеджер может редактировать заголовки, текст преимуществ и фото, но ни при каких обстоятельствах не может случайно удалить форму заявки, добавить посторонние блоки или переставить секции местами. Какая комбинация настроек решает задачу?
version: 2#В WordPress 6.6+ используется спецификация "version": 3. В ней появились поддержка CSS-селекторов псевдоклассов (:hover, :focus), расширенные возможности типографики и переопределение стилей дочерних элементов блоков. Использование устаревшей схемы лишает тему поддержки современных дизайн-токенов.
allowed_block_types_all#Если забыть проверить empty($context->post) в хуке allowed_block_types_all, в Редакторе сайта (Site Editor) исчезнут служебные блоки core/template-part, core/post-content и core/navigation. Пользователь увидит белый экран или сообщение о невозможности отрендерить шаблон сайта.
!important в CSS#Разработчики часто пытаются переопределить цвета блоков ядра через селекторы с !important в файле style.css. Это ломает специфичность стилей: когда администратор выбирает цвет блока в инспекторе, сгенерированный инлайн-стиль ядра перебивается внешним CSS, вызывая баги отображения. Цвета должны объявляться исключительно через палитру theme.json.