Управление версиями @import стиля родительской темы.

28

контекст

Я построил детскую тему, основанную на Двадцать тринадцать, которая работает довольно хорошо. После обновления родительской темы до версии 1.3 я заметил странное поведение со стилем, вызванным кэшированной родительской темой style.css.

Вот содержание моей дочерней темы style.css(без заголовков)

/* =Imports styles from the parent theme
-------------------------------------------------------------- */
@import url('../twentythirteen/style.css');

Таким образом, дочерняя тема не style.cssделает ничего, кроме импорта родительской темы style.css.

У меня также есть другой файл css с настройками моей дочерней темы, который я ставлю в очередь следующим образом functions.php:

// Enqueue parent theme's style.css (faster than using @import in our style.css)
$themeVersion = wp_get_theme()->get('Version');

// Enqueue child theme customizations
wp_enqueue_style('child_main', get_stylesheet_directory_uri() . '/css/main.css',
    null, $themeVersion);

Это дает мне очень хороший URL-адрес CSS, как это: он domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1гарантирует, что таблица стилей перезагружается при обновлении дочерней темы.

Теперь проблема

Заявление @import url('../twentythirteen/style.css');полностью не зависит от версии основной родительской темы. Фактически, родительская тема может быть обновлена ​​без обновления дочерней темы, но браузеры будут по-прежнему использовать старые версии, сохраненные в кэше ../twentythirteen/style.css.

Соответствующий код в Двадцать тринадцать, который ставит в очередь style.css:

function twentythirteen_scripts_styles() {
    // ...

    // Add Genericons font, used in the main stylesheet.
    wp_enqueue_style( 'genericons', get_template_directory_uri() . '/genericons/genericons.css', array(), '3.03' );

    // Loads our main stylesheet.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
    // Note usage of get_stylesheet_uri() which actually enqueues child-theme/style.css

    // Loads the Internet Explorer specific stylesheet.
    wp_enqueue_style( 'twentythirteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentythirteen-style' ), '2013-07-18' );
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Я могу придумать несколько способов решения этой проблемы, но ни один из них не является действительно удовлетворительным:

  1. Обновляйте мою дочернюю тему каждый раз, когда обновляется родительская тема, чтобы изменить строку версии в style.css(например @import url('../twentythirteen/style.css?ver=NEW_VERSION');). Это создает ненужную и раздражающую связь между версией родительской темы и дочерней.

  2. В моем ребенке functions.php, 1) wp_dequeue_styleвключенный ребенок ТЕМА style.cssи 2) родительская тема это непосредственна строка версии. Это портит порядок очереди CSS в родительской теме.wp_enqueue_stylestyle.css

  3. Используйте style_loader_tagфильтр, чтобы изменить сгенерированный <link>тег css style.cssи изменить путь так, чтобы он указывал непосредственно на строку WITH версии родительской темы style.css. Кажется довольно неясным для такой распространенной необходимости (перебора кеша).

  4. Дамп родительской темы style.cssв моей дочерней теме style.css. То же, что (1) на самом деле, но немного быстрее.

  5. Сделайте мою дочернюю тему style.cssсимволической ссылкой на родительскую тему style.css. Это кажется довольно хакерским ...

Я что-то пропустил? Какие-либо предложения?

редактировать

Добавлены genericicons.cssи ie.cssтаблицы стилей в родительской теме , чтобы выяснить , почему я не могу изменить @importзаявление CSS , чтобы wp_enqueue_styleв моей детской теме. В настоящее время с @importзаявлением в моей дочерней теме style.css, у меня есть этот порядок на сгенерированных страницах:

  1. fiftythirteen / genericons / genericons.css -> в родительской теме
  2. child-theme / style.css -> добавленный в родительскую тему, @imports fiftythirteen / style.css
  3. двадцать тринадцать / css / ie.css -> в родительской теме
  4. child-theme / css / main.css -> добавлена ​​в дочернюю тему

Если я поставлю родителей style.cssв зависимость main.css, это станет:

  1. fiftythirteen / genericons / genericons.css -> в родительской теме
  2. child-theme / style.css -> пусто, поставлено в очередь родительской темой
  3. двадцать тринадцать / css / ie.css -> в родительской теме
  4. fiftythirteen / style.css -> добавлена ​​в дочернюю тему как зависимость от main.css
  5. child-theme / css / main.css -> добавлена ​​в дочернюю тему

Обратите внимание, что ie.css теперь включен перед темой родительской темы style.css. Я не хочу менять порядок постановки в очередь css-файлов родительской темы, потому что не могу предположить, что это не вызовет проблем с приоритетом правил css.

Bernie
источник
5
Никогда не используйте @import, вместо этого установите таблицу стилей родительской темы как зависимость от вашей собственной таблицы стилей .
fuxia
Я знаю, что это не лучший подход, но он рекомендуется здесь: codex.wordpress.org/Child_Themes
Берни
Кроме того, выполнение того, что вы предложили, не решает мою проблему. Родительская тема style.cssне будет включена в то же место, что и сейчас. Родитель включает в себя другие файлы CSS, которые должны находиться между его style.cssи моей дочерней темой CSS.
Берни
3
Пожалуйста, полностью игнорируйте кодекс. Он полон дезинформации. Использование параметра зависимости будет включать таблицы стилей в правильном порядке.
fuxia
Пожалуйста, смотрите мое редактирование.
Берни

Ответы:

19

Вам не нужно использовать @import. На самом деле это лучше не делать. Использование поставленного в очередь подхода, вероятно, лучше всего вокруг.

Вот соответствующая часть двадцать тринадцатого кода:

function twentythirteen_scripts_styles() {
...
    // Loads our main stylesheet.
    wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' );
...
}
add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' );

Вот что вы делаете в своем коде:

function child_scripts_styles() {
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('twentythirteen-style'), 'YOUR_THEME_VERSION' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Если ваш main.css должен следовать за родительским style.css, то вы просто делаете его зависимым от этого.

Теперь, если у вас также есть B.css в дочернем элементе, вы устанавливаете зависимости соответствующим образом:

function child_scripts_styles() {
    wp_enqueue_style( 'child-B-style', get_stylesheet_directory_uri().'/B.css', array('twentythirteen-style'), 'YOUR_THEME_VERSION' );
    wp_enqueue_style( 'child-style', get_stylesheet_directory_uri().'/css/main.css', array('child-B-style'), 'YOUR_THEME_VERSION' );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Сделайте зависимости, которые вы определяете для каждого элемента, фактически отражающими, каковы эти зависимости на самом деле. Если main.css должен идти после B.css, то это зависит от него. Если B.css должен идти после style.css родителя, то B зависит от этого. Система постановки в очередь разберутся за вас.

И если вы не используете дочерний стиль style.css ни для чего, вам не нужно ставить его в очередь . Это может быть просто заполнитель для хранения информации заголовка вашей темы. Не используете это? Не загружайте это.

Кроме того, что именно вы делаете, это так зависит от заказа здесь? CSS не заботится о порядке загрузки в большинстве ситуаций. CSS больше зависит от специфики селекторов. Если вы хотите переопределить что-то, вы сделаете свой селектор для этого более конкретным. Он может быть первым, последним или чем-то промежуточным, более конкретный селектор всегда побеждает.

редактировать

Читая ваши комментарии и присматриваясь к коду, я вижу, в чем здесь ошибка. Двадцать тринадцать кодов ставит в очередь функцию «get_stylesheet_uri ()», которая в случае дочерней темы будет файлом style.css вашей дочерней темы, а не файлом родительского. Вот почему @import работает и сохраняет тот же порядок (что, опять же, не так важно, как вы думаете).

В этом случае, если вы не хотите использовать импорт, я бы порекомендовал поставить в очередь родительский файл style.css напрямую. Вот так:

function child_scripts_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri().'/style.css', array() );
}
add_action( 'wp_enqueue_scripts', 'child_scripts_styles' );

Сначала запускается код в functions.php дочерней темы, поэтому сначала запускается собственный wp_enqueue_scripts, и это ставит в очередь родительскую тему style.css, которую родительская тема не выполняет сама (потому что она фактически ставит в очередь style.css вашего ребенка). Не заставляя его зависеть ни от чего, так же как и от родителя, он просто корректно помещается в вывод. Обратите внимание, что порядок этого файла и genericons.css не имеет значения, потому что исходный «стиль в стиле двадцать тринадцати» не имеет genericons.css в качестве указанной зависимости.

Загрузится style.css вашего собственного ребенка, и, честно говоря, именно здесь вы должны поместить свои изменения для дочерней темы, а не в отдельный main.css. Ничто не мешает вам внести ваши изменения, но нет никакой реальной причины иметь дополнительный файл CSS.

эфирное масло
источник
Я полностью согласен, что @importэто не лучший путь. Пожалуйста, смотрите мой раздел "редактировать" для более точной информации. У меня нет особых требований в отношении заказа CSS. Я просто не хочу изменять внутренний порядок css-файлов родительской темы, что может вызвать проблемы с приоритетом css-правил.
Берни
Для пояснения, B.css (теперь измененный на ie.css) не является частью моей дочерней темы, но фактически является частью родительской темы.
Берни
2
Если вы хотите, чтобы ваш стиль соответствовал стилю ie.css, тогда сделайте так, чтобы ваш собственный стиль зависел от него. Его зовут «двадцать тринадцать». Порядок полностью зависит от того, какие зависимости вы объявляете, но опять же, с помощью CSS, фактический порядок их в документе обычно не имеет значения, поэтому я не уверен, почему вы слишком сильно заботитесь об этом.
Отто
2
Отредактировал мой ответ, чтобы включить другой подход.
Отто
Да, я думаю, что я увлекся необходимостью держать порядок в css. Если порядок действительно важен для родительской темы, это должно быть указано в зависимостях.
Берни
9

Мой предыдущий ответ слишком сложен и потенциально не учитывает цепочку зависимостей родительской темы (см. Примечание в другом ответе).

Вот еще один гораздо более простой способ, который должен работать намного лучше:

function use_parent_theme_stylesheet() {
    // Use the parent theme's stylesheet
    return get_template_directory_uri() . '/style.css';
}

function my_theme_styles() {
    $themeVersion = wp_get_theme()->get('Version');

    // Enqueue our style.css with our own version
    wp_enqueue_style('child-theme-style', get_stylesheet_directory_uri() . '/style.css',
        array(), $themeVersion);
}

// Filter get_stylesheet_uri() to return the parent theme's stylesheet 
add_filter('stylesheet_uri', 'use_parent_theme_stylesheet');

// Enqueue this theme's scripts and styles (after parent theme)
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Идея состоит в том, чтобы просто отфильтровать вызов get_stylesheet_uri()в родительской теме, чтобы получить собственную таблицу стилей вместо дочерней темы. Таблица стилей дочерней темы затем ставится в очередь в хуке действия my_theme_styles.

Bernie
источник
Просто для записи: 1) Ваш код будет генерировать точно такой же HTML, как и при использовании старой @importверсии, никакого влияния на производительность вообще не будет, будет два отдельных запроса style.css к серверу 2) Этот ответ отбрасывает всю зависимость целиком вместе ... 3) Вы можете проверить, что get_template_directory_uriи get_template_stylesheet_uriделаете здесь: core.trac.wordpress.org/browser/tags/4.8/src/wp-include/… Опять же, большая часть этого кода не требуется.
17
1
@ bg17aw using wp_enqueue_styleавтоматически добавляет строку запроса на удаление кэша к URL-адресу, который она генерирует (например ?ver=2013-07-18) в зависимости от версии темы. Это не сделано @importзаявлением.
Берни
2

предупреждение

Это решение не учитывает зависимости родительской темы ! Изменение имени дескриптора родительской темы влияет на цепочку зависимостей, установленных в родительской теме. Смотрите мой гораздо более простой ответ .

оригинальный ответ

Хотя ответ Отто довольно хороший, я закончил с этим в функциях моей дочерней темы.

function my_theme_styles() {
    global $wp_styles;
    $parentOriginalHandle = 'twentythirteen-style';
    $parentNewHandle = 'parent-style';

    // Deregister our style.css which was enqueued by the parent theme; we want
    // to control the versioning ourself.
    $parentStyleVersion = $wp_styles->registered[$parentOriginalHandle]->ver;
    $parentDeps = $wp_styles->registered[$parentOriginalHandle]->deps;
    wp_deregister_style($parentOriginalHandle);

    // Enqueue the parent theme's style.css with whatever version it used instead
    // of @import-ing it in the child theme's style.css
    wp_register_style($parentNewHandle, get_template_directory_uri() . '/style.css',
        $parentDeps, $parentStyleVersion);

    // Enqueue our style.css with our own version
    $themeVersion = wp_get_theme()->get('Version');
    wp_enqueue_style($parentOriginalHandle, get_stylesheet_directory_uri() . '/style.css',
        [$parentNewHandle], $themeVersion);
}

// Run this action action the parent theme has enqueued its styles.
add_action('wp_enqueue_scripts', 'my_theme_styles', 20);

Он поддерживает style.cssпорядок и номера версий родительской темы, одновременно контролируя версию дочерней темы style.css.

Bernie
источник
5
Меня поражает, что наиболее популярному программному обеспечению для блогов требуется более 20 строк кода, чтобы настроить CSS существующей темы. Я думаю, это безопасность работы.
Карл Дж
Я должен был измениться [$parentNewHandle]наarray($parentNewHandle)
Карл Дж
@CarlG: синтаксис массива, который я использовал (скобки), был введен в PHP 5.4.
Берни
Upvoters: пожалуйста, посмотрите мой другой ответ, который решает проблемы с этим.
Берни
Это огромное недоразумение, в этом нет необходимости. На самом деле старый @importметод работает так же хорошо, пожалуйста, сравните оба метода. Что касается зависимости дочерней темы от родительской темы, то в этом также нет необходимости. Ребенок style.cssвсегда загружается после родителя, по крайней мере, из моих тестов. Люблю быть ошибочным.
17