WordPress : Versioning @import du style.css du thème parent

Publié par Jean-Michel le

Le contexte

J’ai construit un thème enfant basé sur Twenty Thirteen qui fonctionne plutôt bien. Après avoir mis à jour le thème parent vers la version 1.3, j’ai remarqué un comportement étrange avec le style causé par un thème parent mis en cache style.css.

Voici le contenu de mon thème enfant style.css(en omettant les en-têtes)

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

Ainsi, le thème enfant style.cssne fait rien de plus qu’importer le fichier style.css.

J’ai aussi un autre fichier css avec les personnalisations de mon thème enfant que je mets en file d’attente comme suit 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);

Cela me donne une très belle url css comme celle-ci : domain.com/wp-content/themes/toutprettoutbon/css/main.css?ver=1.0.1qui s’assure que la feuille de style est rechargée lorsque le thème enfant est mis à jour.

maintenant le problème

La déclaration @import url('../twentythirteen/style.css');est complètement indépendante de la version du thème parent sous-jacent. En fait, le thème parent peut être mis à jour sans mettre à jour le thème enfant, mais les navigateurs utiliseront toujours les versions en cache de l’ancien ../twentythirteen/style.css.

Code pertinent dans Twenty Thirteen qui met en file d’attente 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' );

Je peux penser à plusieurs façons de résoudre ce problème, mais aucune n’est vraiment satisfaisante:

  1. Mettre à jour mon thème enfant chaque fois que le thème parent est mis à jour pour modifier une chaîne de version dans style.css(par exemple @import url('../twentythirteen/style.css?ver=NEW_VERSION');). Cela crée un lien inutile et ennuyeux entre la version du thème parent et l’enfant.

  2. Dans mon enfant functions.php, 1) wp_dequeue_stylele thème enfant inclus style.csset 2) wp_enqueue_stylele thème parentstyle.css directement AVEC la chaîne de version. Cela perturbe l’ordre des CSS en file d’attente dans le thème parent.

  3. Utilisez le filtre pour modifier la balise style_loader_tagCSS générée et modifiez le chemin pour qu’il pointe directement vers le thème parent AVEC une chaîne de version. Cela semble plutôt obscur pour un besoin aussi courant (cache busting).<link>style.cssstyle.css

  4. Vider le thème parent style.cssdans le fichier style.css. Identique à (1) vraiment, mais un peu plus rapide.

  5. Faire en sorte que mon thème enfant style.csssoit un lien symbolique vers le thème parent style.css. Cela semble assez bidon…

Ai-je raté quelque chose ? Aucune suggestion?

Éditer

Ajout genericicons.cssde ie.cssfeuilles de style dans le thème parent pour clarifier pourquoi je ne peux pas modifier l’ @importinstruction css wp_enqueue_styledans mon thème enfant. Actuellement, avec une @importdéclaration dans mon thème enfant style.css, j’ai cet ordre dans les pages générées :

  1. vingt-treize/genericons/genericons.css -> mis en file d’attente par le thème parent
  2. child-theme/style.css -> mis en file d’attente par le thème parent, @imports Twentythirteen/style.css
  3. vingt-treize/css/ie.css -> mis en file d’attente par le thème parent
  4. child-theme/css/main.css -> mis en file d’attente par thème enfant

Si je mets en file d’attente le parent en style.csstant que dépendance de main.css, cela deviendra:

  1. vingt-treize/genericons/genericons.css -> mis en file d’attente par le thème parent
  2. child-theme/style.css -> vide, mis en file d’attente par le thème parent
  3. vingt-treize/css/ie.css -> mis en file d’attente par le thème parent
  4. vingt-treize/style.css -> mis en file d’attente par le thème enfant en tant que dépendance de main.css
  5. child-theme/css/main.css -> mis en file d’attente par thème enfant

Notez que ie.css est maintenant inclus avant le thème parent style.css. Je ne veux pas changer l’ordre de mise en file d’attente des fichiers CSS du thème parent car je ne peux pas présumer que cela ne causera pas de problèmes avec la priorité des règles CSS.

Solution n°1 trouvée

Ma réponse précédente est trop compliquée et ne respecte potentiellement pas la chaîne de dépendance du thème parent (voir la note dans une autre réponse).

Voici une autre prise beaucoup plus simple qui devrait fonctionner beaucoup mieux :

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);

L’idée est de simplement filtrer l’appel à get_stylesheet_uri()dans le thème parent pour renvoyer sa propre feuille de style au lieu de celle du thème enfant. La feuille de style du thème enfant est ensuite mise en file d’attente plus tard dans le crochet d’action my_theme_styles.

Solution n°2 trouvée

Vous n’êtes pas obligé d’utiliser @import. Il vaut mieux ne pas le faire, en fait. L’utilisation d’une approche en file d’attente est probablement meilleure tout autour.

Voici la partie pertinente du code de vingt-treize :

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' );

Voici ce que vous faites dans votre code :

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' );

Si votre main.css doit venir après le style.css du parent, alors il suffit de le rendre dépendant de cela.

Maintenant, si vous avez également un B.css dans l’enfant, configurez les dépendances en conséquence :

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' );

Faites en sorte que les dépendances que vous définissez pour chaque élément reflètent réellement ce que sont réellement ces dépendances. Si main.css doit venir après B.css, cela en dépend. Si B.css doit venir après le style.css du parent, alors B en dépend. Le système de mise en file d’attente s’en chargera pour vous.

Et si vous n’utilisez pas réellement le style.css de l’enfant pour quoi que ce soit, vous n’avez pas du tout à le mettre en file d’attente . Il peut s’agir simplement d’un espace réservé pour contenir les informations d’en-tête de votre thème. Vous ne l’utilisez pas ? Ne le chargez pas.

De plus, que faites-vous exactement qui dépend tellement de la commande ici ? CSS ne se soucie pas de l’ordre de chargement dans la plupart des situations. CSS dépend davantage de la spécificité des sélecteurs. Si vous souhaitez remplacer quelque chose, vous rendez votre sélecteur plus spécifique. Il peut venir en premier, en dernier ou n’importe quoi entre les deux, le sélecteur le plus spécifique l’emporte toujours.

Éditer

En lisant vos commentaires et en regardant de plus près le code, je vois où se trouve l’erreur ici. Le code vingt-treize met en file d’attente le « get_stylesheet_uri() », qui dans un cas de thème enfant, serait le fichier style.css de votre thème enfant, pas le fichier du parent. C’est pourquoi @import fonctionne et conserve le même ordre (ce qui, encore une fois, n’a pas autant d’importance que vous le pensez).

Dans ce cas, si vous ne souhaitez pas utiliser l’importation, je vous recommande de mettre directement en file d’attente le fichier style.css du parent. Ainsi:

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

Le code dans functions.php du thème enfant s’exécute en premier, donc vos propres wp_enqueue_scripts s’exécuteront en premier, et cela mettra en file d’attente le style.css du thème parent, ce que le thème parent ne fait pas lui-même (car il met en file d’attente le style.css de votre enfant). En ne le faisant dépendre de rien, comme le parent, il est simplement placé correctement dans la sortie. Notez que l’ordre de ce fichier et de genericons.css n’a pas d’importance, car le « style vingt-treize » d’origine n’a pas le genericons.css comme dépendance répertoriée.

Le style.css de votre propre enfant se chargera, et honnêtement, c’est là que vous devez mettre vos modifications pour le thème enfant, pas dans un main.css séparé. Rien ne vous empêche d’y mettre vos modifications, mais il n’y a aucune raison réelle d’avoir un fichier CSS supplémentaire.

Solution n°3 trouvée

Attention

Cette solution ne respecte pas les dépendances du thème parent ! La modification du nom du handle du thème parent affecte la chaîne de dépendances définie dans le thème parent. Voir mon autre réponse beaucoup plus simple.

réponse originale

Bien que la réponse d’Otto soit plutôt bonne, je me suis retrouvé avec cela dans functions.php de mon thème enfant

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);

Il conserve l’ordre et les numéros de version du thème parent style.csstout en contrôlant la version du thème enfant style.css.

Catégories : Wordpress

Jean-Michel

Jean-Michel est en charge de la partie blog du site. Il met en place la stratégie de contenu et répond aux questions fréquentes sur Wordpress.

0 commentaire

Laisser un commentaire

Avatar placeholder

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *