Проблемы с подключением стилей родительской и дочерней темы при использовании обновленного метода из Codex
Этот пост поднимает несколько вопросов, с которыми я столкнулся относительно недавних изменений в методах подключения таблиц стилей, упомянутых в этой теме и этой теме.
Проблемы возникли в типичном сценарии использования, с широко используемой и хорошо поддерживаемой родительской темой, которая специально подготовлена для дочерних тем на WP 4.0. Файл functions.php моей дочерней темы содержит только функцию wp_enqueue_style
, как описано в Кодексе.
Обратите внимание, что хотя приведенный ниже код специфичен для этой темы, большая его часть использует текущие соглашения о кодировании, применяемые родительскими темами. Кроме того, мои проблемные области, вероятно, можно воспроизвести на большом количестве существующих родительских тем. Также эти вопросы применимы на универсальном уровне, независимо от используемой родительской темы.
ПРОБЛЕМА 1: Двойное подключение
Рекомендуемая настройка:
Родительская тема подключает стили и скрипты с помощью хука wp_enqueue_scripts
, соответствующая часть выглядит следующим образом:
add_action('wp_enqueue_scripts', 'parent_theme_function_name');
function parent_theme_function_name() {
wp_register_style( 'avia-style' , $child_theme_url."/style.css", array(), '2', 'all' );
wp_enqueue_style( 'avia-base');
if($child_theme_url != $template_url) { wp_enqueue_style( 'avia-style'); }
}
Мой файл functions.php дочерней темы подключает стили согласно недавним изменениям в кодексе:
add_action( 'wp_enqueue_scripts', 'enqueue_parent_theme_style' );
function enqueue_parent_theme_style() {
wp_enqueue_style( 'dm-parent-style', get_template_directory_uri().'/style.css' );
}
Обратите внимание на следующие ID, используемые в коде:
id='dm-parent-style-css'
- таблица стилей родительской темы, подключенная функцией моей дочерней темыid='avia-style-css'
- таблица стилей моей дочерней темы, подключенная функцией родительской темыid='dm-child-style-css'
- таблица стилей моей дочерней темы, подключенная функцией моей дочерней темы
Результаты:
На первый взгляд все было в порядке, в <head>
отображался следующий порядок:
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
После установки плагина порядок подключения изменился следующим образом:
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->
В конечном итоге мне нужно, чтобы CSS моей дочерней темы загружался после всех плагинов, поэтому я был вынужден добавить приоритет к функции в моей дочерней теме (см. предыдущее обсуждение относительно приоритетного номера).
Однако, поскольку моя функция подключает только CSS родительской темы, результат таков, что теперь CSS родительской темы перемещается в конец, оставляя CSS моей дочерней темы в еще худшем положении, чем раньше.
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
Теперь я вынужден подключать стиль дочерней темы также, чтобы гарантировать его загрузку в начале, что приводит к упомянутой выше проблеме двойного подключения (новый термин? лол) CSS дочерней темы.
Устаревшая настройка:
Измененная функция в дочерней теме:
add_action( 'wp_enqueue_scripts', 'enqueue_parent_theme_style', 99 );
function enqueue_parent_theme_style() {
wp_enqueue_style( 'dm-parent-style', get_template_directory_uri().'/style.css' );
wp_enqueue_style( 'dm-child-style', get_stylesheet_directory_uri().'/style.css' );
}
Результаты:
Приводит к следующему порядку в <head>
:
<!-- Multiple individual parent theme styles here -->
<link rel='stylesheet' id='avia-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
<!-- Pesky plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<link rel='stylesheet' id='dm-child-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
Несмотря на то, что включение таблицы стилей дочерней темы в мою функцию привело к ее двойному подключению, ИМХО это предпочтительнее, чем программирование с предположением, что родительская тема правильно подключит таблицу стилей дочерней темы за нас. Основываясь на ID, присвоенных каждому подключенному стилю, похоже, что родительская тема подключает его, а не что-то в ядре WP.
Мое решение:
Хотя я вряд ли предложил бы это в качестве рекомендуемого метода (и я уверен, что разработчики с большим опытом кодирования будут стонать от этого решения), я отключил ID родительской темы (используемый для подключения стиля моей дочерней темы) прямо перед моим собственным подключением в файле functions.php моей дочерней темы, как показано:
add_action( 'wp_enqueue_scripts', 'enqueue_parent_theme_style', 99 );
function enqueue_parent_theme_style() {
wp_enqueue_style( 'dm-parent-style', get_template_directory_uri().'/style.css' );
wp_dequeue_style( 'avia-style' );
wp_enqueue_style( 'dm-child-style', get_stylesheet_directory_uri().'/style.css' );
}
Результаты:
Это решило текущие проблемы, в результате чего получилось:
<!-- Multiple individual parent theme styles here -->
<!-- Plugin styles -->
<link rel='stylesheet' id='dm-parent-style-css' href='testinstall.dev/wp-content/themes/enfold/style.css?ver=4.0' type='text/css' media='all' />
<link rel='stylesheet' id='dm-child-style-css' href='testinstall.dev/wp-content/themes/child-theme/style.css?ver=2' type='text/css' media='all' />
Конечно, это требовало знания ID, используемого родительской темой - что-то более универсальное потребовалось бы для использования в качестве стандартной методологии разработки дочерних тем.
ПРОБЛЕМА 2: Перемещенные таблицы стилей дочерней темы
(Кажется невероятным, что это не поднималось в другой теме, хотя я не видел конкретных при поиске... если я пропустил, пожалуйста, дайте мне знать.)
Я никогда не использую стандартный style.css
в корневом каталоге дочерней темы для стилей темы - он, очевидно, должен быть там, но все мои реальные стили компилируются из SCSS как минифицированный .css файл в директории /css/. Хотя я понимаю, что это не "ожидаемая норма" на универсальном уровне для разработки дочерних тем, большинство серьезных разработчиков WordPress, которых я знаю, делают что-то подобное. Это, конечно, требует ручного подключения этой таблицы стилей в моей функции независимо от того, подключила ли ее родительская тема или нет.
Подводя итоги...
- Безопасно ли предполагать, что родительские темы правильно подключают стили дочерней темы, с точки зрения стандартов дочерних тем?
- Удаление приоритета может потенциально создать больше путаницы для части сообщества WordPress, когда стили дочерней темы начинают перезаписываться плагином. Мы ожидаем, что темы перезаписывают стили, но не так сильно с плагинами.
- При использовании пользовательской таблицы стилей для фактических стилей дочерней темы (в отличие от размещения их в предопределенном
style.css
), ручное подключение этого файла становится необходимым. С точки зрения поддержания преемственности среди широкого спектра разработчиков, не имеет ли смысла поощрять ручное подключение таблицы стилей дочерней темы независимо от возможного дублирования?

ВОПРОС 1
Безопасно ли предполагать, что родительские темы правильно подключают стили дочерней темы, с точки зрения стандартов дочерних тем?
Как общее правило, да. Но вы никогда не должны предполагать. Большинство катастроф и неудач в жизни происходят из-за предположений или фактов, основанных на предположениях.
ФАКТЫ БЕЗ ПРЕДПОЛОЖЕНИЙ
Файл functions.php дочерней темы загружается первым, затем functions.php родительской темы. Это гарантирует, что основной файл стилей родительской темы загружается перед основным файлом стилей дочерней темы, согласно обновлённому коду в кодексе.
Давайте посмотрим на встроенную тему twentytwelve. Всё волшебство происходит здесь:
wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );
. Так подключается основной файл стилей. Когда тема активна как родительская, style.css загружается из родительской темы, так какget_stylesheet_uri()
указывает на style.css в директории родительской темы.Когда вы переключаетесь на дочернюю тему,
get_stylesheet_uri()
"изменяет" свой путь, указывая на style.css дочерней темы. Это означает, что теперьwp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );
загружает style.css дочерней темы вместо родительской.Все остальные стили родительской темы загружаются как обычно, в порядке их указания.
ПОДВОДНЫЕ КАМНИ
Встроенные стили и таблицы стилей, добавленные напрямую в шаблон header.php. Я проводил тестирование по этому вопросу. Если основной файл стилей родительской темы не подключён с помощью
wp_enqueue_scripts
, а загружается напрямую в header, то основной файл стилей дочерней темы загружается первым. В качестве решения я ранее рекомендовал копировать header.php родительской темы в дочернюю тему и удалять эти вызовы. Затем вам нужно будет подключить стили как родительской, так и дочерней темы, а также любые другие таблицы стилей, которые были загружены напрямую в header.php, как описано в OP устаревшая функция.Я сталкивался с этим пару раз: стили (и скрипты) загружаются напрямую в header, и из-за этого вызов
wp_head
пропускается. Это приведёт к тихому сбою вашего действия enqueue, и ваши стили просто не появятся.Неправильно установленные приоритеты. Не обязательно устанавливать приоритеты в действиях родительской и дочерней тем при подключении функций enqueue. Когда у обоих одинаковый приоритет по умолчанию, применяется правило "первым пришёл — первым обслужен". Это гарантирует правильный порядок загрузки.
ЗАМЕТКА ДЛЯ АВТОРОВ РОДИТЕЛЬСКИХ ТЕМ
Правильный и принятый метод добавления стилей и скриптов в тему — через хук действия wp_enqueue_scripts
. Никогда не добавляйте стили и скрипты напрямую в шаблон header и не устанавливайте приоритет в вашем действии при подключении функции.
Всегда загружайте основной файл стилей следующим образом:
wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() );
Это гарантирует, что основной файл стилей дочерней темы будет загружен, когда используется дочерняя тема.
ВАША ОТВЕТСТВЕННОСТЬ КАК АВТОРА ДОЧЕРНЕЙ ТЕМЫ
Уделите время и изучите родительскую тему. Знайте свою родительскую тему, убедитесь, что вы понимаете структуру темы и как в ней используются функции и хуки. Вы не сможете создать успешную дочернюю тему, если не будете знать, как работает родительская тема. Ваша ответственность — убедиться, что стили и скрипты загружаются в правильном порядке, чтобы ваш код работал, как ожидается.
Всегда сообщайте автору родительской темы о любом коде, который вас не устраивает. Например, если автор добавил стили напрямую в header, сообщите ему об этом и объясните, что это неправильный способ, попросите исправить это в будущем релизе.
ВОПРОС 2
Удаление приоритета может потенциально создать больше путаницы для части сообщества WordPress, когда стили дочерней темы начинают перезаписываться плагином. Мы ожидаем, что темы будут перезаписывать стили, но не так часто плагины.
К сожалению, нет прямого метода защититься от этого. Факт в том, что стили плагинов никогда не должны перезаписывать стандартные стили темы без согласия конечного пользователя. На мой взгляд, это просто плохая практика или небрежность со стороны автора плагина. Я бы предложил в таком случае связаться с автором плагина и сообщить ему об этом.
У вас также всегда есть возможность отключить и снять регистрацию стиля (и скрипта), который вам не нужен, или который вам нужно изменить в приоритете, а затем снова подключить и зарегистрировать их, как в вашем коде выше (что совершенно нормально). Просто заметка о вашем shivm: лучшая практика — это отключить и снять регистрацию стиля и скрипта.
ВОПРОС 3
При использовании пользовательской таблицы стилей для фактических стилей дочерней темы (вместо размещения их в предопределённом style.css) требуется ручное подключение этого файла. С точки зрения поддержания согласованности среди широкого спектра разработчиков, не имеет ли смысла поощрять ручное подключение таблицы стилей дочерней темы, несмотря на возможное дублирование?
Я не думаю, что на этот вопрос есть однозначный ответ. Я бы ответил так: делайте то, что вам удобно, если это соответствует определённым руководящим принципам, регулирующим действие.
Таблицы стилей нужны не для добавления функциональности, а для улучшения визуального восприятия пользователя. Стили также отправляются в браузер "как есть", где и обрабатываются. WordPress здесь не играет никакой роли.
Исходя из этого факта, я действительно не вижу никаких угрожающих красных флагов в двойной загрузке таблицы стилей. Это может стоить несколько миллисекунд производительности. Честно говоря, помимо этого, я не уверен, как дубликаты обрабатываются в разных браузерах. Это то, что вы, как читатель, можете проверить самостоятельно.
IMHO, дубликаты никогда не являются хорошей идеей, и их следует избегать. Я бы предложил, если вы действительно хотите вручную подключить основной файл стилей дочерней темы по какой-либо причине, использовать ваш код в вашем shivm. Отключите и снимите регистрацию дубликата, добавленного по умолчанию, а затем снова подключите таблицу стилей как обычно.
Ещё одна вещь, которую стоит помнить: функции enqueue и register имеют параметр $dependancy
, которым вы также можете воспользоваться. Так что легко загрузить дополнительную таблицу стилей и сделать её зависимой от основной таблицы стилей вашей дочерней темы.
В ЗАКЛЮЧЕНИЕ
С момента последнего обновления кодекса отзывы были потрясающими, и я хотел бы поблагодарить всех за обратную связь по этому вопросу. Я бы хотел поощрить всех участвовать в любых видах обратной связи по этому конкретному вопросу. Если у вас есть что добавить или прокомментировать, пожалуйста, сделайте это.

Питер, спасибо за твой подробный ответ. Сегодня был очень загружен, но у меня есть несколько мыслей по поводу сказанного тобой, которые я надеюсь добавить позже вечером.
