Дочерняя тема WordPress: зачем нужна и как сделать за полчаса
Правки в теме слетают после обновления. Как создать дочернюю тему, что в неё переносить и когда достаточно сниппета вместо неё.
Содержание
- Почему правки в теме исчезают
- Что такое дочерняя тема и как она работает
- Минимальная дочерняя тема: два файла
- Как подключать стили без старого @import
- Что переносить в дочернюю тему, а что нет
- Когда дочерняя тема не нужна
- Переезд правок в дочернюю тему без простоя
- Чек-лист проверки после переключения
- Сколько это стоит
- Частые вопросы
Дочерняя тема WordPress собирается из двух файлов: style.css с заголовком и указанием родителя и functions.php с подключением стилей. Полчаса работы избавляют от главной беды правок в теме: очередное обновление стирает их без предупреждения.
Классика жанра: подрядчик два года назад поправил телефон в шапке прямо в файлах темы, всё работало, а после планового обновления шапка вернулась к заводскому виду. Вместе с ней уехали кастомные поля в карточке товара и блок с реквизитами в подвале. Дочерняя тема WordPress придумана ровно против этого сценария: она даёт место, где ваши правки переживут любое обновление родителя. Ниже разберу, как собрать её за полчаса, что в неё переносить, а что не надо, и в каких случаях она вообще лишняя.

Я веду абонентку шестой год, и правки в родительской теме встречаю примерно у каждого третьего нового клиента. Иногда их находишь не сразу: сайт выглядит нормально, пока не нажмёшь кнопку обновления.
Почему правки в теме исчезают
Обновление темы в WordPress устроено грубо. Ядро скачивает новый архив, удаляет старую папку целиком и распаковывает новую на её место. Никакого мержа, никакого сравнения файлов, никакого «у вас тут изменения, оставить?». Всё, что лежало в /wp-content/themes/astra/, перестаёт существовать.
Поэтому строка, которую вы вписали в footer.php, живёт ровно до следующего апдейта. У популярных тем это 8-15 релизов в год. Astra в 2025 году выпустила 14 версий, Kadence около десяти. Значит, средний срок жизни вашей правки в родительской теме — месяц.
Отдельная неприятность в том, что сайт после такого обновления обычно не падает. Он продолжает работать, просто без вашей функциональности. Никакого белого экрана и алерта в мониторинге, и вы узнаёте о потере, когда клиент спрашивает, куда делась форма расчёта.
По моему опыту, восстановление слетевших правок стоит дороже, чем изначально стоило сделать их правильно. Найти, что именно было изменено, обычно можно только через сравнение с бэкапом или через git diff, если репозиторий вёлся. Если бэкапов старше недели нет, а обновление было три недели назад, восстанавливать нечего: приходится переписывать заново по памяти и по скриншотам из архива Wayback Machine.
Живой пример из практики. Салон в Кронштадте, тема OceanWP, в functions.php родителя сидели три вещи: отключение эмодзи, подмена текста кнопки в форме заявки и хук, который слал уведомление в Telegram. После обновления перестали приходить заявки. Не сломались, а именно перестали доходить, форма при этом отправлялась и показывала спасибо. Владелец заметил через шесть дней, потому что у него в среднем две заявки в день и он списал тишину на сезон. Двенадцать потерянных обращений.
Что такое дочерняя тема и как она работает
Дочерняя тема это отдельная папка в /wp-content/themes/, которая объявляет родителя и наследует от него всё: шаблоны, функции, стили, поддержку блоков. Активируется в админке она сама, родитель при этом должен оставаться установленным, но не активным.
Механика простая и держится на двух правилах.
Правило первое: шаблоны замещаются. Если WordPress ищет single.php и находит его в дочерней теме, родительский игнорируется полностью. То же самое для header.php, footer.php, page.php, woocommerce/single-product.php и любого другого файла из иерархии шаблонов.
Правило второе: functions.php не замещается, а добавляется. Файл дочерней темы подключается ПЕРЕД родительским. Это часто ломает мозг новичкам: они копируют весь functions.php родителя в дочернюю и получают фатальную ошибку про повторное объявление функции. Копировать functions.php нельзя, в него только дописывают своё.
Для блочных тем (Twenty Twenty-Five и подобные) добавляется третий слой: theme.json дочерней темы не замещает родительский, а мержится с ним по ключам. Переопределяете только те токены, которые реально меняете, остальное подтягивается сверху.
Минимальная дочерняя тема: два файла
Нужны ровно два файла. Третий (screenshot.png) косметический, но с ним в списке тем не будет серой заглушки.
Создайте папку /wp-content/themes/astra-child/ и положите туда style.css:
/*
Theme Name: Astra Child
Theme URI: https://example.ru/
Description: Дочерняя тема для Astra. Все правки клиента живут здесь.
Author: Дмитрий
Template: astra
Version: 1.0.0
Text Domain: astra-child
*/
Критично только поле Template: в нём указывается имя ПАПКИ родительской темы, не её человеческое название. Не Astra, а astra. Не Kadence, а kadence. Ошибка в регистре или лишний пробел дают белый экран с текстом «The parent theme is missing».
Второй файл, functions.php:
<?php
add_action( 'wp_enqueue_scripts', 'sf_child_styles', 20 );
function sf_child_styles() {
$parent = wp_get_theme()->parent();
wp_enqueue_style(
'astra-child',
get_stylesheet_uri(),
array( 'astra-theme-css' ),
wp_get_theme()->get( 'Version' )
);
}
Всё, тема готова, её уже можно активировать. Дальше в этот style.css пишутся CSS-правки, а в functions.php дописываются хуки.
Если есть доступ к WP-CLI, всю заготовку делает одна команда, и она же сразу проставляет корректный enqueue:
wp scaffold child-theme astra-child --parent_theme=astra
--theme_name="Astra Child" --author="Дмитрий"
wp theme activate astra-child
Как подключать стили без старого @import
В гайдах десятилетней давности стиль родителя подтягивали через @import url("../astra/style.css") в первой строке дочернего CSS. Так делать не надо уже лет восемь. @import блокирует параллельную загрузку: браузер сначала скачивает дочерний файл, парсит его, только потом идёт за родительским. На мобильном 3G это лишние 200-400 мс к первой отрисовке.
Правильный способ зависит от того, как родитель регистрирует свои стили.
Вариант первый, родитель регистрирует стиль с известным хендлом (Astra, GeneratePress, Kadence, Blocksy). Тогда достаточно объявить его зависимостью, как в примере выше. Хендл смотрится в исходниках родителя поиском по wp_enqueue_style или в HTML страницы по атрибуту id у тега link: astra-theme-css-css означает хендл astra-theme-css.
Вариант второй, родитель ничего внятного не регистрирует (часто у самописных и старых тем с ThemeForest). Тогда подключаем оба файла вручную:
add_action( 'wp_enqueue_scripts', 'sf_child_styles', 20 );
function sf_child_styles() {
$parent_ver = wp_get_theme()->parent()->get( 'Version' );
$child_ver = wp_get_theme()->get( 'Version' );
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css', array(), $parent_ver );
wp_enqueue_style( 'child-style', get_stylesheet_uri(), array( 'parent-style' ), $child_ver );
}
Две функции, которые надо перестать путать раз и навсегда:
| Функция | Что возвращает при активной дочерней теме |
|---|---|
get_template_directory() | путь к папке РОДИТЕЛЯ |
get_stylesheet_directory() | путь к папке ДОЧЕРНЕЙ темы |
get_template_directory_uri() | URL папки родителя |
get_stylesheet_uri() | URL файла style.css дочерней темы |
get_parent_theme_file_path() | путь к файлу родителя, безопасный современный аналог |
Практическое следствие: если вы кладёте в дочернюю тему картинку или шрифт и подключаете её через get_template_directory_uri(), получите 404, потому что файл ищется у родителя. Это причина примерно половины «почему у меня логотип не грузится» в дочерних темах.
Про версию в третьем аргументе. Указывайте её всегда, иначе WordPress подставит версию ядра, а на сайтах с агрессивным кэшем (а он агрессивный почти везде: браузерный кэш обычно ставят на год) правки в CSS просто не доедут до посетителя. Тратить час на поиск несуществующего бага в стилях из-за забытого ?ver= обидно. На своих проектах я подставляю filemtime() от файла, тогда версия меняется автоматически при каждом сохранении.
Что переносить в дочернюю тему, а что нет
Механическое копирование родителя в дочернюю встречается часто и всегда заканчивается плохо: при обновлении родителя его шаблоны получают новую разметку и новые хуки, а у вас лежит замороженная копия годичной давности, которая уже не совместима с новой версией. Класть в дочернюю тему нужно минимум.
| Что | Куда | Комментарий |
|---|---|---|
| CSS-правки | style.css дочерней | Только те селекторы, что реально меняете |
| Свои хуки и фильтры | functions.php дочерней | Дописывать, не копировать родительский файл |
Изменённый single.php, header.php | копия файла в дочерней | Копировать целиком, менять точечно |
| Шаблоны WooCommerce | woocommerce/... в дочерней | Структура папок повторяет родителя |
| Свои картинки, шрифты | assets/ в дочерней | Подключать через get_stylesheet_directory_uri() |
functions.php родителя | НЕ копировать | Фатальная ошибка при повторном объявлении функций |
Правки в ядре /wp-includes/ | НЕ трогать вообще | Слетит при первом же апдейте WordPress |
| Настройки плагинов | не сюда | Они в базе, тема на них не влияет |
Отдельно про подмену функций. У родительских тем часто встречаются функции, обёрнутые в if ( ! function_exists( 'astra_footer_markup' ) ). Такие можно переопределить целиком в дочерней теме: она грузится первее, её версия побеждает. Если обёртки нет, переопределять нечего, работайте через хуки:
// Убрать родительский вывод и поставить свой
add_action( 'after_setup_theme', function () {
remove_action( 'astra_footer', 'astra_footer_markup', 10 );
add_action( 'astra_footer', 'sf_custom_footer', 10 );
} );
function sf_custom_footer() {
get_template_part( 'template-parts/footer', 'custom' );
}
Тонкость с remove_action: приоритет и имя функции должны совпасть с теми, что были при регистрации, до символа. Указали 10 вместо 20 и удаление молча не сработает, ошибки не будет никакой. Проверять удобнее всего плагином Query Monitor, вкладка Hooks and Actions.
Когда дочерняя тема не нужна
Скажу непопулярное: в половине случаев, когда её просят, она избыточна. Дочерняя тема нужна тогда, когда вы правите ШАБЛОНЫ. Если задача сводится к CSS или паре хуков, есть варианты дешевле в поддержке.
Только CSS. В Кастомайзере есть раздел «Дополнительные стили», туда можно писать сколько угодно. Плюс: правки живут в базе и переживают обновление темы. Минус: они привязаны к активной теме и потеряются при смене темы, а ещё их неудобно версионировать. Для 20-30 строк нормально, для 500 уже нет.
Только функции. Плагин Code Snippets (бесплатный, около 900 тысяч установок) или WPCode. Каждый хук лежит отдельной записью, включается и выключается тумблером, при фатальной ошибке плагин сам отключает битый сниппет и не роняет сайт. Для клиента, который время от времени лезет сам, это безопаснее, чем править functions.php через файловый редактор.
Блочная тема с полным редактированием сайта (FSE). Twenty Twenty-Four и новее позволяют менять шаблоны прямо в редакторе, а результат кладут в базу как записи типа wp_template. Обновление темы их не трогает. Дочерняя тема тут пригодится, только если нужен PHP.
Тема куплена и обновляется через личный кабинет автора. Такие темы (особенно с ThemeForest) в 70 процентах случаев уже содержат папку child-theme внутри архива. Не делайте свою, распакуйте авторскую: в ней уже прописаны нужные хендлы стилей.
И обратный случай, когда дочерняя тема обязательна: конструктор шаблонов вроде Elementor Pro или Bricks не используется, а вам нужно переписать разметку карточки товара, добавить свой тип шаблона или подключить кастомный template-part. Тут без неё никак.
Кстати, если тема на сайте скачана с торрента или «активирована» нуллед-версией, дочерняя тема проблему не решает: там обычно зашит бэкдор, и правильная архитектура правок ничего не меняет. Про это подробнее в разборе рисков нуллед-тем и плагинов.
Переезд правок в дочернюю тему без простоя
Самая нервная часть, если сайт живой и правок накопилось много. Порядок, по которому я это делаю у клиентов.
Шаг 1. Найти все правки в родительской теме. Если исходный архив темы доступен, сравнение делается в лоб:
cd /tmp && wget https://downloads.wordpress.org/theme/astra.4.11.6.zip
unzip -q astra.4.11.6.zip -d original
diff -rq original/astra /var/www/site/wp-content/themes/astra
diff -rq покажет список отличающихся файлов. Дальше по каждому смотрите обычный diff и выписываете изменения. На типовом сайте это 3-8 файлов и час работы.
Шаг 2. Собрать дочернюю тему по инструкции выше и перенести в неё найденные изменения. Шаблоны копируются из ОРИГИНАЛЬНОЙ версии темы, а не из правленой: так вы сразу получите актуальную разметку и наложите на неё только свои куски.
Шаг 3. Проверить на копии. Переключение темы на живом сайте без теста это лотерея, поэтому сначала разворачиваем staging и активируем дочернюю там. Заодно увидите, что именно отвалится.
Шаг 4. Перенести настройки Кастомайзера. Вот тут все спотыкаются: настройки Кастомайзера хранятся в опции theme_mods_<папка темы>, и при активации дочерней темы WordPress берёт theme_mods_astra-child, которой ещё нет. Меню отваливаются от позиций, виджеты уезжают в неактивные, логотип пропадает.
wp option get theme_mods_astra --format=json > /tmp/mods.json
wp option update theme_mods_astra-child --format=json < /tmp/mods.json
Заодно перенесите дополнительный CSS из Кастомайзера. Он лежит в записях типа custom_css, где post_title равен слагу темы:
UPDATE wp_posts SET post_title = 'astra-child'
WHERE post_type = 'custom_css' AND post_title = 'astra';
Шаг 5. Активировать на бою и сразу пройтись по чек-листу проверки. Само переключение занимает секунды, откат тоже: активируете родителя обратно, и сайт возвращается к прежнему виду.
Чек-лист проверки после переключения
Порядок обхода, который у меня в регламенте. Занимает минут пятнадцать.
- Главная: логотип, меню в шапке, слайдер, подвал с реквизитами.
- Внутренняя страница и запись блога: боковая колонка, хлебные крошки, шрифты.
- Архив рубрики и пагинация.
- Страница 404 и результаты внутреннего поиска.
- Формы: отправка заявки реально доходит до почты или в Telegram, чекбокс согласия на месте, письмо приходит.
- Корзина и оформление заказа, если есть магазин. Тестовый заказ на 1 рубль.
- Админка: редактор Гутенберга открывается, стили блоков подтянулись, Кастомайзер не пустой.
- Мобильная версия: гамбургер-меню открывается и закрывается.
- Консоль браузера: нет 404 по CSS, шрифтам и картинкам.
- PageSpeed на главной до и после: цифры не должны просесть.
Последний пункт не формальность. Если стили родителя подключились дважды (типичная ошибка при ручном enqueue, когда родитель уже подключает себя сам), вес страницы вырастет на размер CSS темы, а это у Astra порядка 60 КБ, у некоторых мультитем до 400 КБ. Проверяется во вкладке Network поиском по style.css: файл должен грузиться по одному разу с каждой темы.
Плановые обновления после переезда становятся спокойнее, но не превращаются в кнопку «обновить всё сразу». Механику безопасного апдейта разбирал отдельно в статье про обновление WordPress без поломок.
Сколько это стоит
Если делаете сами и правок мало, полчаса-час. Если правок много и они не задокументированы, время уходит на археологию, а не на код.
Мои ориентиры по работе под ключ: чистая дочерняя тема с переносом CSS и двух-трёх хуков это 3 000-5 000 рублей и один рабочий день с проверкой на копии. Сайт, где родительскую тему правили три года подряд разные подрядчики, а бэкапов старше месяца нет, это 8 000-15 000 и два-три дня, потому что половина времени уходит на поиск отличий и восстановление логики по кускам.
В абонентском обслуживании такая работа обычно укладывается в месячный лимит часов и отдельно не считается: для меня это профилактика, после которой обновления перестают быть источником сюрпризов. Что в абонентку не входит никогда: разработка сайта с нуля и дизайн, я занимаюсь чужими готовыми сайтами.
Один совет напоследок. Заведите в дочерней теме файл CHANGELOG.md и пишите туда одной строкой, что и когда меняли. Через два года, когда вы или следующий подрядчик откроете functions.php и увидите там хук с непонятным назначением, эта строка сэкономит час гадания. У меня такой файл есть на каждом проекте под абонемент, и клиенты, которые от меня уходили, потом писали спасибо именно за него.
Если тема на вашем сайте правилась напрямую и вы не знаете, что уцелело после последних обновлений, напишите мне: сравню текущие файлы с оригиналом темы, покажу список расхождений и скажу, что там ценного. Диагностика такого рода занимает у меня час и делается до начала любых работ.
Частые вопросы
Зачем нужна дочерняя тема
Чтобы правки пережили обновление родительской темы. Всё, что изменено прямо в файлах темы, при следующем апдейте возвращается к заводскому виду вместе с вашим телефоном в шапке.
Как сделать дочернюю тему
Создать папку, положить в неё style.css с заголовком и строкой Template с именем родительской темы, добавить functions.php и подключить в нём стили родителя через wp_enqueue_style. Дальше переключиться на новую тему в админке.
Что переносить в дочернюю тему
Изменённые файлы шаблонов и свой CSS. Функции лучше держать не в теме, а в отдельном плагине или в сниппетах: при смене темы они не должны пропадать.
Когда дочерняя тема не нужна
Когда тема написана под проект и никогда не обновляется из каталога. И когда правка сводится к паре строк CSS: их проще положить в настройки темы, чем разводить отдельную сущность.